diff --git a/app/src/main/java/com/tangem/tap/di/domain/StakingDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/StakingDomainModule.kt index 10f1264ba6..c280208083 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/StakingDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/StakingDomainModule.kt @@ -144,4 +144,16 @@ internal object StakingDomainModule { stakingErrorResolver = stakingErrorResolver, ) } + + @Provides + @Singleton + fun provideIsStakeMoreAvailableUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): IsStakeMoreAvailableUseCase { + return IsStakeMoreAvailableUseCase( + stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, + ) + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt index fc7dab4bd6..4d6ff9ca76 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt @@ -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 + @POST("actions/exit") + suspend fun createExitAction(@Body body: ActionRequestBody): ApiResponse + @POST("actions/enter/estimate-gas") suspend fun estimateGasOnEnter(@Body body: ActionRequestBody): ApiResponse 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 5249e59c74..cab788363d 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 @@ -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, currencyId: String, symbol: String): Yield? { return yields.find { it.token.coinGeckoId == currencyId && it.token.symbol == symbol } } diff --git a/data/staking/src/main/java/com/tangem/data/staking/converters/action/EnterActionResponseConverter.kt b/data/staking/src/main/java/com/tangem/data/staking/converters/action/EnterActionResponseConverter.kt index 888d805305..c228248f43 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/converters/action/EnterActionResponseConverter.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/converters/action/EnterActionResponseConverter.kt @@ -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 { +) : Converter { - 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), diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/EnterAction.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/StakingAction.kt similarity index 95% rename from domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/EnterAction.kt rename to domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/StakingAction.kt index c8b8a639f5..5922003ad7 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/EnterAction.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/StakingAction.kt @@ -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, diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingTransactionUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingTransactionUseCase.kt index 12107bff68..2c843b9161 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingTransactionUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingTransactionUseCase.kt @@ -18,7 +18,7 @@ class GetStakingTransactionUseCase( suspend operator fun invoke(params: ActionParams): Either { 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) diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/IsStakeMoreAvailableUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/IsStakeMoreAvailableUseCase.kt new file mode 100644 index 0000000000..30e148dccd --- /dev/null +++ b/domain/staking/src/main/java/com/tangem/domain/staking/IsStakeMoreAvailableUseCase.kt @@ -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 { + return Either + .catch { stakingRepository.isStakeMoreAvailable(networkId) } + .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 3776a2e27b..a374a30d09 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 @@ -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, ): 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 } \ 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 1c27d431af..68589655af 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 @@ -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 } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt index 64e66f66d8..e9a6ec4c62 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt @@ -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) {} } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingClickIntents.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingClickIntents.kt index 0173545ee9..05d121258a 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingClickIntents.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingClickIntents.kt @@ -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() diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt index 5549b2dbf0..157dfbebf4 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt @@ -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