diff --git a/data/staking/build.gradle.kts b/data/staking/build.gradle.kts index 017cc43973..6bcc1ccd0b 100644 --- a/data/staking/build.gradle.kts +++ b/data/staking/build.gradle.kts @@ -21,8 +21,10 @@ dependencies { /** Domain modules */ implementation(projects.domain.tokens.models) implementation(projects.domain.staking) + implementation(projects.domain.wallets) implementation(projects.domain.wallets.models) implementation(projects.domain.legacy) + implementation(projects.domain.models) /** Feature Api modules */ implementation(projects.features.staking.api) @@ -39,8 +41,8 @@ dependencies { implementation(deps.moshi) implementation(deps.moshi.kotlin) - implementation(projects.libs.blockchainSdk) + implementation(projects.libs.crypto) implementation(deps.tangem.card.core) implementation(deps.tangem.blockchain) { diff --git a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt index 562d6d1bd7..c17d722c51 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt @@ -1,6 +1,7 @@ package com.tangem.data.staking import android.util.Base64 +import arrow.core.getOrElse import arrow.core.raise.catch import com.squareup.moshi.Moshi import com.tangem.blockchain.common.Blockchain @@ -51,9 +52,11 @@ import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.orZero +import com.tangem.lib.crypto.BlockchainUtils.isSolana import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch @@ -69,6 +72,7 @@ internal class DefaultStakingRepository( private val dispatchers: CoroutineDispatcherProvider, private val stakingFeatureToggle: StakingFeatureToggles, private val walletManagersFacade: WalletManagersFacade, + private val getUserWalletUseCase: GetUserWalletUseCase, moshi: Moshi, ) : StakingRepository { @@ -159,17 +163,19 @@ internal class DefaultStakingRepository( } } - override suspend fun getStakingAvailabilityForActions( - cryptoCurrencyId: CryptoCurrency.ID, - symbol: String, + override suspend fun getStakingAvailability( + userWalletId: UserWalletId, + cryptoCurrency: CryptoCurrency, ): StakingAvailability { - val rawCurrencyId = cryptoCurrencyId.rawCurrencyId ?: return StakingAvailability.Unavailable + if (checkForInvalidCardBatch(userWalletId, cryptoCurrency)) return StakingAvailability.Unavailable + + val rawCurrencyId = cryptoCurrency.id.rawCurrencyId ?: return StakingAvailability.Unavailable return withContext(dispatchers.io) { val yields = getEnabledYields() ?: return@withContext StakingAvailability.Unavailable - val prefetchedYield = findPrefetchedYield(yields, rawCurrencyId, symbol) - val isSupported = isStakingSupported(getIntegrationKey(cryptoCurrencyId)) + val prefetchedYield = findPrefetchedYield(yields, rawCurrencyId, cryptoCurrency.symbol) + val isSupported = isStakingSupported(getIntegrationKey(cryptoCurrency.id)) when { prefetchedYield != null && isSupported -> { @@ -183,6 +189,21 @@ internal class DefaultStakingRepository( } } + private fun checkForInvalidCardBatch(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean { + val userWallet = getUserWalletUseCase(userWalletId).getOrElse { + error("Failed to get user wallet") + } + + return when { + isSolana(cryptoCurrency.network.id.value) -> { + INVALID_BATCHES_FOR_SOLANA.contains(userWallet.scanResponse.card.batchId) + } + else -> { + false + } + } + } + override suspend fun createAction( userWalletId: UserWalletId, network: Network, @@ -625,6 +646,8 @@ internal class DefaultStakingRepository( const val ETHEREUM_POLYGON_APPROVE_SPENDER = "0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908" + val INVALID_BATCHES_FOR_SOLANA = listOf("AC01", "CB79") + // uncomment items as implementation is ready val integrationIdMap = mapOf( Blockchain.Solana.run { id + toCoinId() } to SOLANA_INTEGRATION_ID, diff --git a/data/staking/src/main/java/com/tangem/data/staking/di/StakingDataModule.kt b/data/staking/src/main/java/com/tangem/data/staking/di/StakingDataModule.kt index 32a9a1cdae..fc2baff6dd 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/di/StakingDataModule.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/di/StakingDataModule.kt @@ -14,6 +14,7 @@ import com.tangem.datasource.local.token.StakingYieldsStore import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.walletmanager.WalletManagersFacade +import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module @@ -37,6 +38,7 @@ internal object StakingDataModule { stakingFeatureToggle: StakingFeatureToggles, cacheRegistry: CacheRegistry, walletManagersFacade: WalletManagersFacade, + getUserWalletUseCase: GetUserWalletUseCase, @NetworkMoshi moshi: Moshi, ): StakingRepository { return DefaultStakingRepository( @@ -48,6 +50,7 @@ internal object StakingDataModule { cacheRegistry = cacheRegistry, stakingFeatureToggle = stakingFeatureToggle, walletManagersFacade = walletManagersFacade, + getUserWalletUseCase = getUserWalletUseCase, moshi = moshi, ) } diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingAvailabilityUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingAvailabilityUseCase.kt index 46a2f010be..7133219a03 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingAvailabilityUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingAvailabilityUseCase.kt @@ -6,6 +6,7 @@ import com.tangem.domain.staking.model.stakekit.StakingError import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.wallets.models.UserWalletId /** * Use case for getting info about staking capability in tangem app. @@ -16,11 +17,16 @@ class GetStakingAvailabilityUseCase( ) { suspend operator fun invoke( - cryptoCurrencyId: CryptoCurrency.ID, - symbol: String, + userWalletId: UserWalletId, + cryptoCurrency: CryptoCurrency, ): Either { return Either - .catch { stakingRepository.getStakingAvailabilityForActions(cryptoCurrencyId, symbol) } + .catch { + stakingRepository.getStakingAvailability( + userWalletId = userWalletId, + cryptoCurrency = cryptoCurrency, + ) + } .mapLeft { stakingErrorResolver.resolve(it) } } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingRepository.kt b/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingRepository.kt index 69016e1209..f95af53048 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingRepository.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingRepository.kt @@ -32,10 +32,7 @@ interface StakingRepository { suspend fun getYield(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): Yield - suspend fun getStakingAvailabilityForActions( - cryptoCurrencyId: CryptoCurrency.ID, - symbol: String, - ): StakingAvailability + suspend fun getStakingAvailability(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): StakingAvailability suspend fun fetchSingleYieldBalance( userWalletId: UserWalletId, diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt index 99ec404379..a1e112bb15 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt @@ -129,14 +129,13 @@ class GetCryptoCurrencyActionsUseCase( // staking if (stakingFeatureToggles.isStakingEnabled) { - if (isStakingAvailable(cryptoCurrency)) { + if (isStakingAvailable(userWallet, cryptoCurrency)) { val yield = kotlin.runCatching { stakingRepository.getYield( cryptoCurrencyId = cryptoCurrency.id, symbol = cryptoCurrency.symbol, ) }.getOrNull() - activeList.add( TokenActionsState.ActionState.Stake( unavailabilityReason = ScenarioUnavailabilityReason.None, @@ -301,10 +300,10 @@ class GetCryptoCurrencyActionsUseCase( return networkAddress != null && networkAddress.defaultAddress.value.isNotEmpty() } - private suspend fun isStakingAvailable(cryptoCurrency: CryptoCurrency): Boolean { - return stakingRepository.getStakingAvailabilityForActions( - cryptoCurrencyId = cryptoCurrency.id, - symbol = cryptoCurrency.symbol, + private suspend fun isStakingAvailable(userWallet: UserWallet, cryptoCurrency: CryptoCurrency): Boolean { + return stakingRepository.getStakingAvailability( + userWalletId = userWallet.walletId, + cryptoCurrency = cryptoCurrency, ) is StakingAvailability.Available } } \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockStakingRepository.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockStakingRepository.kt index 9bc782020a..3000900a10 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockStakingRepository.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockStakingRepository.kt @@ -113,9 +113,9 @@ class MockStakingRepository : StakingRepository { isAvailable = false, ) - override suspend fun getStakingAvailabilityForActions( - cryptoCurrencyId: CryptoCurrency.ID, - symbol: String, + override suspend fun getStakingAvailability( + userWalletId: UserWalletId, + cryptoCurrency: CryptoCurrency, ): StakingAvailability = StakingAvailability.Unavailable override suspend fun fetchSingleYieldBalance( diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt index f959f9632a..949d9deaa0 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt @@ -393,8 +393,8 @@ internal class TokenDetailsViewModel @Inject constructor( private fun updateStakingInfo() { viewModelScope.launch { val stakingAvailability = getStakingAvailabilityUseCase( - cryptoCurrencyId = cryptoCurrency.id, - symbol = cryptoCurrency.symbol, + userWalletId = userWalletId, + cryptoCurrency = cryptoCurrency, ).getOrElse { StakingAvailability.Unavailable } internalUiState.value = stateFactory.getStateWithUpdatedStakingAvailability(stakingAvailability)