Updated on 2026-08-14

This commit is contained in:
Tangem 2025-06-11 17:09:20 +05:00
parent 8dc9304c06
commit ab27ff4bea
4 changed files with 86 additions and 16 deletions

View file

@ -246,6 +246,47 @@ internal class DefaultStakingRepository(
} }
} }
override suspend fun getStakingAvailabilitySync(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
): StakingAvailability {
if (!checkFeatureToggleEnabled(cryptoCurrency.network.id)) {
return StakingAvailability.Unavailable
}
if (checkForInvalidCardBatch(userWalletId, cryptoCurrency)) {
return StakingAvailability.Unavailable
}
val rawCurrencyId = cryptoCurrency.id.rawCurrencyId
if (rawCurrencyId == null) {
return StakingAvailability.Unavailable
}
val isSupportedInMobileApp = getSupportedIntegrationId(cryptoCurrency.id).isNullOrEmpty().not()
val yields = getEnabledYieldsSync()
if (yields.isEmpty()) {
return StakingAvailability.TemporaryUnavailable
}
val prefetchedYield = findPrefetchedYield(
yields = yields,
currencyId = rawCurrencyId,
symbol = cryptoCurrency.symbol,
)
return when {
prefetchedYield != null && isSupportedInMobileApp -> {
StakingAvailability.Available(prefetchedYield.id)
}
prefetchedYield == null && isSupportedInMobileApp -> {
StakingAvailability.TemporaryUnavailable
}
else -> StakingAvailability.Unavailable
}
}
private fun checkFeatureToggleEnabled(networkId: Network.ID): Boolean { private fun checkFeatureToggleEnabled(networkId: Network.ID): Boolean {
return when (networkId.toBlockchain()) { return when (networkId.toBlockchain()) {
Blockchain.TON -> stakingFeatureToggles.isTonStakingEnabled Blockchain.TON -> stakingFeatureToggles.isTonStakingEnabled

View file

@ -32,4 +32,14 @@ class GetStakingAvailabilityUseCase(
it.right() it.right()
}.catch { emit(stakingErrorResolver.resolve(it).left()) } }.catch { emit(stakingErrorResolver.resolve(it).left()) }
} }
suspend fun invokeSync(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
): Either<StakingError, StakingAvailability> = Either.catch {
stakingRepository.getStakingAvailabilitySync(
userWalletId = userWalletId,
cryptoCurrency = cryptoCurrency,
)
}.mapLeft(stakingErrorResolver::resolve)
} }

View file

@ -37,6 +37,11 @@ interface StakingRepository {
fun getStakingAvailability(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Flow<StakingAvailability> fun getStakingAvailability(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Flow<StakingAvailability>
suspend fun getStakingAvailabilitySync(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency,
): StakingAvailability
suspend fun getActions( suspend fun getActions(
userWalletId: UserWalletId, userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency, cryptoCurrency: CryptoCurrency,

View file

@ -3,7 +3,12 @@ package com.tangem.features.staking.impl.deeplink
import arrow.core.getOrElse import arrow.core.getOrElse
import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter import com.tangem.common.routing.AppRouter
import com.tangem.core.deeplink.DeeplinkConst.NETWORK_ID_KEY
import com.tangem.core.deeplink.DeeplinkConst.TOKEN_ID_KEY
import com.tangem.core.deeplink.DeeplinkConst.WALLET_ID_KEY
import com.tangem.domain.staking.GetStakingAvailabilityUseCase
import com.tangem.domain.staking.GetYieldUseCase import com.tangem.domain.staking.GetYieldUseCase
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase import com.tangem.domain.tokens.GetCryptoCurrenciesUseCase
import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
@ -15,6 +20,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
@Suppress("LongParameterList")
internal class DefaultStakingDeepLinkHandler @AssistedInject constructor( internal class DefaultStakingDeepLinkHandler @AssistedInject constructor(
@Assisted private val scope: CoroutineScope, @Assisted private val scope: CoroutineScope,
@Assisted private val queryParams: Map<String, String>, @Assisted private val queryParams: Map<String, String>,
@ -22,6 +28,7 @@ internal class DefaultStakingDeepLinkHandler @AssistedInject constructor(
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase, private val getCryptoCurrenciesUseCase: GetCryptoCurrenciesUseCase,
private val getYieldUseCase: GetYieldUseCase, private val getYieldUseCase: GetYieldUseCase,
private val getStakingAvailabilityUseCase: GetStakingAvailabilityUseCase,
) : StakingDeepLinkHandler { ) : StakingDeepLinkHandler {
init { init {
@ -29,24 +36,28 @@ internal class DefaultStakingDeepLinkHandler @AssistedInject constructor(
} }
private fun handleDeepLink() { private fun handleDeepLink() {
// It is okay here, we are navigating from outside, and there is no other way to getting UserWallet val networkId = queryParams[NETWORK_ID_KEY]
val userWalletId = queryParams[WALLET_ID_KEY]?.let(::UserWalletId) val tokenId = queryParams[TOKEN_ID_KEY]
?: getSelectedWalletSyncUseCase().getOrNull()?.walletId
if (userWalletId == null) { // It is okay here, we are navigating from outside, and there is no other way to getting UserWallet
val selectedUserWalletId = getSelectedWalletSyncUseCase().getOrNull()?.walletId
val walletId = queryParams[WALLET_ID_KEY]?.let(::UserWalletId) ?: selectedUserWalletId
// If selected user wallet is different than from deeplink - ignore deeplink
// If selected user wallet is null - ignore deeplink
if (walletId != selectedUserWalletId || selectedUserWalletId == null) {
Timber.e("Error on getting user wallet") Timber.e("Error on getting user wallet")
return return
} }
val networkId = queryParams[NETWORK_ID_KEY]
val tokenId = queryParams[TOKEN_ID_KEY]
scope.launch { scope.launch {
val cryptoCurrency = getCryptoCurrenciesUseCase(userWalletId = userWalletId).getOrElse { val cryptoCurrency = getCryptoCurrenciesUseCase(userWalletId = selectedUserWalletId).getOrElse {
Timber.e("Error on getting crypto currency list") Timber.e("Error on getting crypto currency list")
return@launch return@launch
}.firstOrNull { }.firstOrNull {
it.network.backendId == networkId && it.id.rawCurrencyId?.value == tokenId val isNetwork = it.network.backendId.equals(networkId, ignoreCase = true)
val isCurrency = it.id.rawCurrencyId?.value?.equals(tokenId, ignoreCase = true) == true
isNetwork && isCurrency
} }
if (cryptoCurrency == null) { if (cryptoCurrency == null) {
@ -60,6 +71,15 @@ internal class DefaultStakingDeepLinkHandler @AssistedInject constructor(
return@launch return@launch
} }
val isStakingEnabled = getStakingAvailabilityUseCase.invokeSync(
userWalletId = selectedUserWalletId,
cryptoCurrency = cryptoCurrency,
).getOrNull()
if (isStakingEnabled !is StakingAvailability.Available) {
return@launch
}
val yield = getYieldUseCase.invoke( val yield = getYieldUseCase.invoke(
cryptoCurrencyId = cryptoCurrency.id, cryptoCurrencyId = cryptoCurrency.id,
symbol = cryptoCurrency.symbol, symbol = cryptoCurrency.symbol,
@ -70,7 +90,7 @@ internal class DefaultStakingDeepLinkHandler @AssistedInject constructor(
appRouter.push( appRouter.push(
AppRoute.Staking( AppRoute.Staking(
userWalletId = userWalletId, userWalletId = selectedUserWalletId,
cryptoCurrencyId = cryptoCurrency.id, cryptoCurrencyId = cryptoCurrency.id,
yieldId = yield.id, yieldId = yield.id,
), ),
@ -85,10 +105,4 @@ internal class DefaultStakingDeepLinkHandler @AssistedInject constructor(
queryParams: Map<String, String>, queryParams: Map<String, String>,
): DefaultStakingDeepLinkHandler ): DefaultStakingDeepLinkHandler
} }
private companion object {
const val WALLET_ID_KEY = "walletId"
const val NETWORK_ID_KEY = "network_id"
const val TOKEN_ID_KEY = "token_id"
}
} }