Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-17 13:58:31 +05:00
commit fb24729e23
12 changed files with 82 additions and 22 deletions

View file

@ -144,4 +144,16 @@ internal object StakingDomainModule {
stakingErrorResolver = stakingErrorResolver,
)
}
@Provides
@Singleton
fun provideIsStakeMoreAvailableUseCase(
stakingRepository: StakingRepository,
stakingErrorResolver: StakingErrorResolver,
): IsStakeMoreAvailableUseCase {
return IsStakeMoreAvailableUseCase(
stakingRepository = stakingRepository,
stakingErrorResolver = stakingErrorResolver,
)
}
}

View file

@ -5,11 +5,11 @@ import com.tangem.datasource.api.stakekit.models.request.*
import com.tangem.datasource.api.stakekit.models.response.EnabledYieldsResponse
import com.tangem.datasource.api.stakekit.models.response.EnterActionResponse
import com.tangem.datasource.api.stakekit.models.response.model.BalanceDTO
import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingTransactionDTO
import com.tangem.datasource.api.stakekit.models.response.model.TokenWithYieldDTO
import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO
import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingGasEstimateDTO
import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingTransactionDTO
import retrofit2.http.*
@Suppress("LongParameterList")
@ -48,6 +48,9 @@ interface StakeKitApi {
@POST("actions/enter")
suspend fun createEnterAction(@Body body: ActionRequestBody): ApiResponse<EnterActionResponse>
@POST("actions/exit")
suspend fun createExitAction(@Body body: ActionRequestBody): ApiResponse<EnterActionResponse>
@POST("actions/enter/estimate-gas")
suspend fun estimateGasOnEnter(@Body body: ActionRequestBody): ApiResponse<StakingGasEstimateDTO>

View file

@ -24,14 +24,15 @@ import com.tangem.datasource.local.token.StakingYieldsStore
import com.tangem.domain.core.lce.LceFlow
import com.tangem.domain.core.lce.lceFlow
import com.tangem.domain.staking.model.*
import com.tangem.domain.staking.model.action.EnterAction
import com.tangem.domain.staking.model.action.StakingAction
import com.tangem.domain.staking.model.action.StakingActionCommonType
import com.tangem.domain.staking.model.transaction.StakingGasEstimate
import com.tangem.domain.staking.model.transaction.ActionParams
import com.tangem.domain.staking.model.transaction.StakingGasEstimate
import com.tangem.domain.staking.model.transaction.StakingTransaction
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -155,10 +156,13 @@ internal class DefaultStakingRepository(
}
}
override suspend fun createEnterAction(params: ActionParams): EnterAction {
override suspend fun createAction(params: ActionParams): StakingAction {
return withContext(dispatchers.io) {
val body = createActionRequestBody(params)
val response = stakeKitApi.createEnterAction(body)
val response = when (params.actionCommonType) {
StakingActionCommonType.ENTER -> stakeKitApi.createEnterAction(body)
StakingActionCommonType.EXIT -> stakeKitApi.createExitAction(body)
}
enterActionResponseConverter.convert(response.getOrThrow())
}
@ -436,6 +440,14 @@ internal class DefaultStakingRepository(
)
}
override fun isStakeMoreAvailable(networkId: Network.ID): Boolean {
val blockchain = Blockchain.fromId(networkId.value)
return when (blockchain) {
Blockchain.Solana -> false
else -> true
}
}
private fun findPrefetchedYield(yields: List<Yield>, currencyId: String, symbol: String): Yield? {
return yields.find { it.token.coinGeckoId == currencyId && it.token.symbol == symbol }
}

View file

@ -2,17 +2,17 @@ package com.tangem.data.staking.converters.action
import com.tangem.data.staking.converters.transaction.StakingTransactionConverter
import com.tangem.datasource.api.stakekit.models.response.EnterActionResponse
import com.tangem.domain.staking.model.action.EnterAction
import com.tangem.domain.staking.model.action.StakingAction
import com.tangem.utils.converter.Converter
class EnterActionResponseConverter(
private val actionStatusConverter: ActionStatusConverter,
private val stakingActionTypeConverter: StakingActionTypeConverter,
private val transactionConverter: StakingTransactionConverter,
) : Converter<EnterActionResponse, EnterAction> {
) : Converter<EnterActionResponse, StakingAction> {
override fun convert(value: EnterActionResponse): EnterAction {
return EnterAction(
override fun convert(value: EnterActionResponse): StakingAction {
return StakingAction(
id = value.id,
integrationId = value.integrationId,
status = actionStatusConverter.convert(value.status),

View file

@ -4,7 +4,7 @@ import com.tangem.domain.staking.model.transaction.StakingTransaction
import org.joda.time.DateTime
import java.math.BigDecimal
data class EnterAction(
data class StakingAction(
val id: String,
val integrationId: String,
val status: StakingActionStatus,

View file

@ -18,7 +18,7 @@ class GetStakingTransactionUseCase(
suspend operator fun invoke(params: ActionParams): Either<StakingError, StakingTransaction> {
return Either.catch {
val createAction = stakingRepository.createEnterAction(params)
val createAction = stakingRepository.createAction(params)
// workaround, sometimes transaction is not created immediately after actions/enter
delay(PATCH_TRANSACTION_REQUEST_DELAY)

View file

@ -0,0 +1,19 @@
package com.tangem.domain.staking
import arrow.core.Either
import com.tangem.domain.staking.model.StakingError
import com.tangem.domain.staking.repositories.StakingErrorResolver
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.Network
class IsStakeMoreAvailableUseCase(
private val stakingRepository: StakingRepository,
private val stakingErrorResolver: StakingErrorResolver,
) {
operator fun invoke(networkId: Network.ID): Either<StakingError, Boolean> {
return Either
.catch { stakingRepository.isStakeMoreAvailable(networkId) }
.mapLeft { stakingErrorResolver.resolve(it) }
}
}

View file

@ -1,16 +1,14 @@
package com.tangem.domain.staking.repositories
import com.tangem.domain.staking.model.StakingAvailability
import com.tangem.domain.staking.model.StakingEntryInfo
import com.tangem.domain.staking.model.Yield
import com.tangem.domain.staking.model.action.EnterAction
import com.tangem.domain.staking.model.transaction.StakingTransaction
import com.tangem.domain.core.lce.LceFlow
import com.tangem.domain.staking.model.*
import com.tangem.domain.staking.model.transaction.StakingGasEstimate
import com.tangem.domain.staking.model.action.StakingAction
import com.tangem.domain.staking.model.transaction.ActionParams
import com.tangem.domain.staking.model.transaction.StakingGasEstimate
import com.tangem.domain.staking.model.transaction.StakingTransaction
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
@ -60,7 +58,7 @@ interface StakingRepository {
addresses: List<CryptoCurrencyAddress>,
): YieldBalanceList
suspend fun createEnterAction(params: ActionParams): EnterAction
suspend fun createAction(params: ActionParams): StakingAction
suspend fun estimateGas(params: ActionParams): StakingGasEstimate
@ -71,4 +69,7 @@ interface StakingRepository {
suspend fun storeUnsubmittedHash(unsubmittedTransactionMetadata: UnsubmittedTransactionMetadata)
suspend fun sendUnsubmittedHashes()
/** Returns whether additional staking is possible if there is already active staking */
fun isStakeMoreAvailable(networkId: Network.ID): Boolean
}

View file

@ -3,13 +3,14 @@ package com.tangem.domain.tokens.repository
import com.tangem.domain.core.lce.LceFlow
import com.tangem.domain.core.lce.lceFlow
import com.tangem.domain.staking.model.*
import com.tangem.domain.staking.model.action.EnterAction
import com.tangem.domain.staking.model.action.StakingAction
import com.tangem.domain.staking.model.action.StakingActionStatus
import com.tangem.domain.staking.model.action.StakingActionType
import com.tangem.domain.staking.model.transaction.*
import com.tangem.domain.staking.repositories.StakingRepository
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyAddress
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow
@ -164,8 +165,8 @@ class MockStakingRepository : StakingRepository {
balances = listOf(YieldBalance.Error),
)
override suspend fun createEnterAction(params: ActionParams): EnterAction {
return EnterAction(
override suspend fun createAction(params: ActionParams): StakingAction {
return StakingAction(
id = "quis",
integrationId = "persequeris",
status = StakingActionStatus.PROCESSING,
@ -224,4 +225,6 @@ class MockStakingRepository : StakingRepository {
override suspend fun sendUnsubmittedHashes() {
/* no-op */
}
override fun isStakeMoreAvailable(networkId: Network.ID): Boolean = true
}

View file

@ -1,6 +1,7 @@
package com.tangem.features.staking.impl.presentation.state.stub
import com.tangem.domain.staking.model.Yield
import com.tangem.features.staking.impl.presentation.state.BalanceState
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
@ -35,4 +36,6 @@ object StakingClickIntentsStub : StakingClickIntents {
override fun onExploreClick() {}
override fun onShareClick() {}
override fun onActiveStake(activeStake: BalanceState) {}
}

View file

@ -2,6 +2,7 @@ package com.tangem.features.staking.impl.presentation.viewmodel
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
import com.tangem.domain.staking.model.Yield
import com.tangem.features.staking.impl.presentation.state.BalanceState
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
internal interface StakingClickIntents : AmountScreenClickIntents {
@ -24,6 +25,8 @@ internal interface StakingClickIntents : AmountScreenClickIntents {
fun selectRewardValidator(rewardValue: String)
fun onActiveStake(activeStake: BalanceState)
fun onExploreClick()
fun onShareClick()

View file

@ -217,6 +217,10 @@ internal class StakingViewModel @Inject constructor(
stakingStateRouter.onNextClick()
}
override fun onActiveStake(activeStake: BalanceState) {
// todo unstake
}
override fun onExploreClick() {
val confirmationDataState = uiState.value.confirmationState as? StakingStates.ConfirmationState.Data
val transactionDoneState = confirmationDataState?.transactionDoneState as? TransactionDoneState.Content