Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-28 14:16:03 +05:00
parent ee69207d9c
commit 87d1885b58
8 changed files with 51 additions and 37 deletions

View file

@ -7,4 +7,5 @@ import com.squareup.moshi.JsonClass
data class YieldSupplyChangeTokenStatusBody(
@Json(name = "tokenAddress") val tokenAddress: String,
@Json(name = "chainId") val chainId: Int,
@Json(name = "userAddress") val userAddress: String,
)

View file

@ -5,12 +5,12 @@ import com.tangem.blockchain.yieldsupply.YieldSupplyProvider
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.blockchainsdk.utils.toNetworkId
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
import com.tangem.data.yield.supply.converters.YieldMarketTokenConverter
import com.tangem.datasource.api.tangemTech.YieldSupplyApi
import com.tangem.data.yield.supply.converters.YieldTokenChartConverter
import com.tangem.datasource.api.common.response.getOrThrow
import com.tangem.datasource.api.tangemTech.YieldSupplyApi
import com.tangem.datasource.api.tangemTech.models.YieldSupplyChangeTokenStatusBody
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.walletmanager.WalletManagersFacade
@ -23,7 +23,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.map
internal class DefaultYieldSupplyRepository(
private val yieldSupplyApi: YieldSupplyApi,
@ -77,7 +76,7 @@ internal class DefaultYieldSupplyRepository(
(walletManager as? YieldSupplyProvider)?.isSupported() ?: false
}
override suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean =
override suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean =
withContext(dispatchers.io) {
val chainId = Blockchain.fromNetworkId(cryptoCurrencyToken.network.backendId)?.getChainId()
?: error("Chain id is required for evm's")
@ -85,11 +84,12 @@ internal class DefaultYieldSupplyRepository(
YieldSupplyChangeTokenStatusBody(
tokenAddress = cryptoCurrencyToken.contractAddress,
chainId = chainId,
userAddress = address,
),
).getOrThrow().isActive
}
override suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean =
override suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean =
withContext(dispatchers.io) {
val chainId = Blockchain.fromNetworkId(cryptoCurrencyToken.network.backendId)?.getChainId()
?: error("Chain id is required for evm's")
@ -97,6 +97,7 @@ internal class DefaultYieldSupplyRepository(
YieldSupplyChangeTokenStatusBody(
tokenAddress = cryptoCurrencyToken.contractAddress,
chainId = chainId,
userAddress = address,
),
).getOrThrow().isActive
}

View file

@ -46,7 +46,7 @@ interface YieldSupplyRepository {
* May throw on network/backend errors or if required chain id cannot be resolved.
*/
@Throws
suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean
suspend fun activateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean
/**
* Deactivate yield protocol for the specified token.
@ -56,7 +56,7 @@ interface YieldSupplyRepository {
* network/backend errors or if required chain id cannot be resolved.
*/
@Throws
suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token): Boolean
suspend fun deactivateProtocol(cryptoCurrencyToken: CryptoCurrency.Token, address: String): Boolean
/**
* Save the last user-initiated yield protocol action for the given currency.

View file

@ -8,8 +8,9 @@ class YieldSupplyActivateUseCase(
private val yieldSupplyRepository: YieldSupplyRepository,
) {
suspend operator fun invoke(cryptoCurrency: CryptoCurrency): Either<Throwable, Boolean> = Either.catch {
val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected")
yieldSupplyRepository.activateProtocol(token)
}
suspend operator fun invoke(cryptoCurrency: CryptoCurrency, address: String): Either<Throwable, Boolean> =
Either.catch {
val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected")
yieldSupplyRepository.activateProtocol(token, address)
}
}

View file

@ -8,8 +8,9 @@ class YieldSupplyDeactivateUseCase(
private val yieldSupplyRepository: YieldSupplyRepository,
) {
suspend operator fun invoke(cryptoCurrency: CryptoCurrency): Either<Throwable, Boolean> = Either.catch {
val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected")
yieldSupplyRepository.deactivateProtocol(token)
}
suspend operator fun invoke(cryptoCurrency: CryptoCurrency, address: String): Either<Throwable, Boolean> =
Either.catch {
val token = cryptoCurrency as? CryptoCurrency.Token ?: error("Token expected")
yieldSupplyRepository.deactivateProtocol(token, address)
}
}

View file

@ -27,19 +27,19 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyIsAvailableUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.YieldSupplyComponent
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
import com.tangem.features.yield.supply.impl.main.model.transformers.YieldSupplyTokenStatusSuccessTransformer
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.DelayedWork
import com.tangem.utils.transformer.update
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import com.tangem.utils.transformer.update
import javax.inject.Inject
import kotlin.properties.Delegates
@ -276,13 +276,14 @@ internal class YieldSupplyModel @Inject constructor(
private fun sendInfoAboutProtocolStatus(cryptoCurrencyStatus: CryptoCurrencyStatus) {
if (lastYieldSupplyStatus == cryptoCurrencyStatus.value.yieldSupplyStatus) return
val token = cryptoCurrency as? CryptoCurrency.Token ?: return
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value ?: return
modelScope.launch(dispatchers.default) {
if (cryptoCurrencyStatus.value.yieldSupplyStatus?.isActive == true) {
yieldSupplyActivateUseCase(token).onRight {
yieldSupplyActivateUseCase(token, address).onRight {
lastYieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
}
} else {
yieldSupplyDeactivateUseCase(token).onRight {
yieldSupplyDeactivateUseCase(token, address).onRight {
lastYieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
}
}

View file

@ -22,13 +22,9 @@ import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.yield.supply.YieldSupplyRepository
import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus
import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyEstimateEnterFeeUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyStartEarningUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.domain.yield.supply.usecase.*
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM
@ -234,10 +230,12 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
ifLeft = { error ->
Timber.e(error.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
analytics.send(YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Approve,
errorDescription = error.getAnalyticsDescription(),
))
analytics.send(
YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Approve,
errorDescription = error.getAnalyticsDescription(),
),
)
yieldSupplyAlertFactory.getSendTransactionErrorState(
error = error,
popBack = params.callback::onBackClick,
@ -255,7 +253,12 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
ifRight = {
yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Enter)
analytics.send(YieldSupplyAnalytics.FundsEarned)
yieldSupplyActivateUseCase(cryptoCurrency)
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {
yieldSupplyActivateUseCase(cryptoCurrency, address)
}
modelScope.launch {
params.callback.onTransactionSent()
}

View file

@ -20,8 +20,8 @@ import com.tangem.domain.yield.supply.YieldSupplyRepository
import com.tangem.domain.yield.supply.models.YieldSupplyEnterStatus
import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyStopEarningUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM
@ -140,10 +140,12 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
ifLeft = { error ->
Timber.e(error.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
analytics.send(YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Stop,
errorDescription = error.getAnalyticsDescription(),
))
analytics.send(
YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Stop,
errorDescription = error.getAnalyticsDescription(),
),
)
yieldSupplyAlertFactory.getSendTransactionErrorState(
error = error,
popBack = params.callback::onBackClick,
@ -166,7 +168,11 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
blockchain = cryptoCurrency.network.name,
),
)
yieldSupplyDeactivateUseCase(cryptoCurrency)
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {
yieldSupplyDeactivateUseCase(cryptoCurrency, address)
}
modelScope.launch {
params.callback.onTransactionSent()
}