Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-26 20:48:51 +05:00
parent 1d06981060
commit 7b5a62d593
10 changed files with 82 additions and 20 deletions

View file

@ -3,6 +3,7 @@ package com.tangem.tap.di.domain
import com.tangem.domain.blockaid.BlockAidGasEstimate import com.tangem.domain.blockaid.BlockAidGasEstimate
import com.tangem.domain.transaction.FeeRepository import com.tangem.domain.transaction.FeeRepository
import com.tangem.domain.transaction.error.FeeErrorResolver import com.tangem.domain.transaction.error.FeeErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
import com.tangem.domain.yield.supply.usecase.* import com.tangem.domain.yield.supply.usecase.*
import dagger.Module import dagger.Module
@ -19,9 +20,11 @@ internal object YieldSupplyDomainModule {
@Singleton @Singleton
fun provideYieldSupplyStartEarningUseCase( fun provideYieldSupplyStartEarningUseCase(
yieldSupplyTransactionRepository: YieldSupplyTransactionRepository, yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
yieldSupplyErrorResolver: YieldSupplyErrorResolver,
): YieldSupplyStartEarningUseCase { ): YieldSupplyStartEarningUseCase {
return YieldSupplyStartEarningUseCase( return YieldSupplyStartEarningUseCase(
yieldSupplyTransactionRepository = yieldSupplyTransactionRepository, yieldSupplyTransactionRepository = yieldSupplyTransactionRepository,
yieldSupplyErrorResolver = yieldSupplyErrorResolver,
) )
} }
@ -29,9 +32,11 @@ internal object YieldSupplyDomainModule {
@Singleton @Singleton
fun provideYieldSupplyStopEarningUseCase( fun provideYieldSupplyStopEarningUseCase(
yieldSupplyTransactionRepository: YieldSupplyTransactionRepository, yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
yieldSupplyErrorResolver: YieldSupplyErrorResolver,
): YieldSupplyStopEarningUseCase { ): YieldSupplyStopEarningUseCase {
return YieldSupplyStopEarningUseCase( return YieldSupplyStopEarningUseCase(
yieldSupplyTransactionRepository = yieldSupplyTransactionRepository, yieldSupplyTransactionRepository = yieldSupplyTransactionRepository,
yieldSupplyErrorResolver = yieldSupplyErrorResolver,
) )
} }
@ -53,9 +58,11 @@ internal object YieldSupplyDomainModule {
@Singleton @Singleton
fun provideYieldSupplyGetContractAddressUseCase( fun provideYieldSupplyGetContractAddressUseCase(
yieldSupplyTransactionRepository: YieldSupplyTransactionRepository, yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
yieldSupplyErrorResolver: YieldSupplyErrorResolver,
): YieldSupplyGetContractAddressUseCase { ): YieldSupplyGetContractAddressUseCase {
return YieldSupplyGetContractAddressUseCase( return YieldSupplyGetContractAddressUseCase(
yieldSupplyTransactionRepository = yieldSupplyTransactionRepository, yieldSupplyTransactionRepository = yieldSupplyTransactionRepository,
yieldSupplyErrorResolver = yieldSupplyErrorResolver,
) )
} }
@ -63,9 +70,11 @@ internal object YieldSupplyDomainModule {
@Singleton @Singleton
fun provideYieldSupplyGetProtocolBalanceUseCase( fun provideYieldSupplyGetProtocolBalanceUseCase(
yieldSupplyTransactionRepository: YieldSupplyTransactionRepository, yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
yieldSupplyErrorResolver: YieldSupplyErrorResolver,
): YieldSupplyGetProtocolBalanceUseCase { ): YieldSupplyGetProtocolBalanceUseCase {
return YieldSupplyGetProtocolBalanceUseCase( return YieldSupplyGetProtocolBalanceUseCase(
yieldSupplyTransactionRepository = yieldSupplyTransactionRepository, yieldSupplyTransactionRepository = yieldSupplyTransactionRepository,
yieldSupplyErrorResolver = yieldSupplyErrorResolver,
) )
} }
} }

View file

@ -0,0 +1,13 @@
package com.tangem.data.yield.supply
import com.tangem.domain.yield.supply.YieldSupplyError
import com.tangem.domain.yield.supply.YieldSupplyErrorResolver
internal data object DefaultYieldSupplyErrorResolver : YieldSupplyErrorResolver {
override fun resolve(throwable: Throwable): YieldSupplyError {
return when (throwable) {
is YieldSupplyError -> throwable
else -> YieldSupplyError.DataError(throwable)
}
}
}

View file

@ -17,6 +17,7 @@ import com.tangem.domain.utils.convertToSdkAmount
import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.orZero
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import timber.log.Timber import timber.log.Timber
import java.math.BigDecimal import java.math.BigDecimal
@ -106,7 +107,7 @@ internal class DefaultYieldSupplyTransactionRepository(
decimals = cryptoCurrency.decimals, decimals = cryptoCurrency.decimals,
), ),
) )
}.onFailure(Timber::e).getOrNull() }.onFailure(Timber::e).getOrThrow()
} }
@Suppress("LongParameterList") @Suppress("LongParameterList")
@ -173,14 +174,16 @@ internal class DefaultYieldSupplyTransactionRepository(
) )
} }
enterTransactions.add( if (cryptoCurrencyStatus.value.amount.orZero() > BigDecimal.ZERO) {
createEnterTransaction( enterTransactions.add(
walletManager = walletManager, createEnterTransaction(
cryptoCurrency = cryptoCurrency, walletManager = walletManager,
amount = amount, cryptoCurrency = cryptoCurrency,
yieldContractAddress = calculatedYieldContractAddress, amount = amount,
), yieldContractAddress = calculatedYieldContractAddress,
) ),
)
}
return enterTransactions return enterTransactions
} }
@ -197,7 +200,7 @@ internal class DefaultYieldSupplyTransactionRepository(
derivationPath = cryptoCurrency.network.derivationPath.value, derivationPath = cryptoCurrency.network.derivationPath.value,
) ?: error("Wallet manager not found") ) ?: error("Wallet manager not found")
walletManager.calculateYieldModuleAddress() walletManager.calculateYieldModuleAddress()
}.onFailure(Timber::e).getOrNull() }.onFailure(Timber::e).getOrThrow()
} }
override suspend fun getYieldContractAddress(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): String? = override suspend fun getYieldContractAddress(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): String? =
@ -210,7 +213,7 @@ internal class DefaultYieldSupplyTransactionRepository(
derivationPath = cryptoCurrency.network.derivationPath.value, derivationPath = cryptoCurrency.network.derivationPath.value,
) ?: error("Wallet manager not found") ) ?: error("Wallet manager not found")
walletManager.getYieldModuleAddress() walletManager.getYieldModuleAddress()
}.onFailure(Timber::e).getOrNull() }.onFailure(Timber::e).getOrThrow()
} }
private suspend fun getYieldTokenStatus( private suspend fun getYieldTokenStatus(
@ -232,7 +235,7 @@ internal class DefaultYieldSupplyTransactionRepository(
isInitialized = sdkSupplyStatus?.isInitialized == true, isInitialized = sdkSupplyStatus?.isInitialized == true,
isAllowedToSpend = isAllowedToSpend, isAllowedToSpend = isAllowedToSpend,
) )
}.onFailure(Timber::e).getOrNull() }.onFailure(Timber::e).getOrThrow()
} }
private fun createDeployTransaction( private fun createDeployTransaction(

View file

@ -1,11 +1,13 @@
package com.tangem.data.yield.supply.di package com.tangem.data.yield.supply.di
import com.tangem.data.yield.supply.DefaultYieldSupplyMarketRepository import com.tangem.data.yield.supply.DefaultYieldSupplyMarketRepository
import com.tangem.data.yield.supply.DefaultYieldSupplyErrorResolver
import com.tangem.data.yield.supply.DefaultYieldSupplyTransactionRepository import com.tangem.data.yield.supply.DefaultYieldSupplyTransactionRepository
import com.tangem.datasource.api.tangemTech.YieldSupplyApi import com.tangem.datasource.api.tangemTech.YieldSupplyApi
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.yield.supply.YieldSupplyMarketRepository import com.tangem.domain.yield.supply.YieldSupplyMarketRepository
import com.tangem.domain.yield.supply.YieldSupplyErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module import dagger.Module
@ -43,4 +45,10 @@ internal object YieldSupplyDataModule {
dispatchers = dispatchers, dispatchers = dispatchers,
) )
} }
@Provides
@Singleton
fun provideYieldSupplyErrorResolver(): YieldSupplyErrorResolver {
return DefaultYieldSupplyErrorResolver
}
} }

View file

@ -0,0 +1,12 @@
package com.tangem.domain.yield.supply
sealed class YieldSupplyError : Throwable() {
abstract val code: Int
data class DataError(
val throwable: Throwable,
) : YieldSupplyError() {
override val code: Int = -1
}
}

View file

@ -0,0 +1,5 @@
package com.tangem.domain.yield.supply
interface YieldSupplyErrorResolver {
fun resolve(throwable: Throwable): YieldSupplyError
}

View file

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

View file

@ -3,22 +3,25 @@ package com.tangem.domain.yield.supply.usecase
import arrow.core.Either import arrow.core.Either
import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.yield.supply.YieldSupplyError
import com.tangem.domain.yield.supply.YieldSupplyErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
import java.math.BigDecimal import java.math.BigDecimal
class YieldSupplyGetProtocolBalanceUseCase( class YieldSupplyGetProtocolBalanceUseCase(
private val yieldSupplyTransactionRepository: YieldSupplyTransactionRepository, private val yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
private val yieldSupplyErrorResolver: YieldSupplyErrorResolver,
) { ) {
suspend operator fun invoke( suspend operator fun invoke(
userWalletId: UserWalletId, userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency, cryptoCurrency: CryptoCurrency,
): Either<Throwable, BigDecimal?> = Either.catch { ): Either<YieldSupplyError, BigDecimal?> = Either.catch {
requireNotNull(cryptoCurrency as CryptoCurrency.Token) requireNotNull(cryptoCurrency as CryptoCurrency.Token)
yieldSupplyTransactionRepository.getProtocolBalance( yieldSupplyTransactionRepository.getProtocolBalance(
userWalletId = userWalletId, userWalletId = userWalletId,
cryptoCurrency = cryptoCurrency, cryptoCurrency = cryptoCurrency,
) )
} }.mapLeft(yieldSupplyErrorResolver::resolve)
} }

View file

@ -4,22 +4,25 @@ import arrow.core.Either
import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.TransactionData
import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.yield.supply.YieldSupplyError
import com.tangem.domain.yield.supply.YieldSupplyErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
import java.math.BigDecimal import java.math.BigDecimal
class YieldSupplyStartEarningUseCase( class YieldSupplyStartEarningUseCase(
private val yieldSupplyTransactionRepository: YieldSupplyTransactionRepository, private val yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
private val yieldSupplyErrorResolver: YieldSupplyErrorResolver,
) { ) {
suspend operator fun invoke( suspend operator fun invoke(
userWalletId: UserWalletId, userWalletId: UserWalletId,
cryptoCurrencyStatus: CryptoCurrencyStatus, cryptoCurrencyStatus: CryptoCurrencyStatus,
maxNetworkFee: BigDecimal, maxNetworkFee: BigDecimal,
): Either<Throwable, List<TransactionData.Uncompiled>> = Either.catch { ): Either<YieldSupplyError, List<TransactionData.Uncompiled>> = Either.catch {
yieldSupplyTransactionRepository.createEnterTransactions( yieldSupplyTransactionRepository.createEnterTransactions(
userWalletId = userWalletId, userWalletId = userWalletId,
cryptoCurrencyStatus = cryptoCurrencyStatus, cryptoCurrencyStatus = cryptoCurrencyStatus,
maxNetworkFee = maxNetworkFee, maxNetworkFee = maxNetworkFee,
) )
} }.mapLeft(yieldSupplyErrorResolver::resolve)
} }

View file

@ -5,21 +5,24 @@ import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.Fee
import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.yield.supply.YieldSupplyError
import com.tangem.domain.yield.supply.YieldSupplyErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
class YieldSupplyStopEarningUseCase( class YieldSupplyStopEarningUseCase(
private val yieldSupplyTransactionRepository: YieldSupplyTransactionRepository, private val yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
private val yieldSupplyErrorResolver: YieldSupplyErrorResolver,
) { ) {
suspend operator fun invoke( suspend operator fun invoke(
userWalletId: UserWalletId, userWalletId: UserWalletId,
cryptoCurrencyStatus: CryptoCurrencyStatus, cryptoCurrencyStatus: CryptoCurrencyStatus,
fee: Fee?, fee: Fee?,
): Either<Throwable, TransactionData.Uncompiled> = Either.catch { ): Either<YieldSupplyError, TransactionData.Uncompiled> = Either.catch {
yieldSupplyTransactionRepository.createExitTransaction( yieldSupplyTransactionRepository.createExitTransaction(
userWalletId = userWalletId, userWalletId = userWalletId,
cryptoCurrencyStatus = cryptoCurrencyStatus, cryptoCurrencyStatus = cryptoCurrencyStatus,
fee = null, fee = null,
) )
} }.mapLeft(yieldSupplyErrorResolver::resolve)
} }