Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-04 15:14:19 +03:00
parent 10d959b0de
commit 679469c91f
7 changed files with 110 additions and 14 deletions

View file

@ -68,6 +68,7 @@ internal class StakingStateRouter(
}
fun showSuccess() {
stateController.update { it.copy(currentStep = StakingStep.Success) }
// stateController.update { it.copy(currentStep = StakingStep.Success) }
// TODO staking [REDACTED_TASK_KEY]
}
}

View file

@ -82,9 +82,15 @@ internal sealed class StakingStates {
val validatorState: ValidatorState,
val notifications: ImmutableList<StakingNotification>,
val footerText: String,
val isSuccess: Boolean,
val isStaking: Boolean,
) : ConfirmStakingState()
val innerState: InnerConfirmStakingState,
) : ConfirmStakingState() {
enum class InnerConfirmStakingState {
CONFIRM,
IN_PROGRESS,
SUCCESS,
}
}
data class Empty(
override val isPrimaryButtonEnabled: Boolean = false,

View file

@ -82,7 +82,6 @@ internal object ConfirmStakingStatePreviewData {
days = 2,
),
),
isStaking = false,
isSuccess = false,
innerState = StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.CONFIRM,
)
}

View file

@ -12,7 +12,7 @@ import com.tangem.utils.transformer.Transformer
import com.tangem.blockchain.common.Amount
@Suppress("UnusedPrivateMember")
internal class SetConfirmStateDataStateTransformer(
internal class SetConfirmStateConfirmTransformer(
private val appCurrencyProvider: Provider<AppCurrency>,
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
private val stakingGasEstimate: StakingGasEstimate,
@ -42,6 +42,8 @@ internal class SetConfirmStateDataStateTransformer(
appCurrency = appCurrencyProvider(),
isFeeApproximate = false,
),
isPrimaryButtonEnabled = true,
innerState = StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.CONFIRM,
)
} else {
return this

View file

@ -0,0 +1,25 @@
package com.tangem.features.staking.impl.presentation.state.transformers
import com.tangem.features.staking.impl.presentation.state.StakingStates
import com.tangem.features.staking.impl.presentation.state.StakingUiState
import com.tangem.utils.transformer.Transformer
internal class SetConfirmStateInProgressTransformer : Transformer<StakingUiState> {
override fun transform(prevState: StakingUiState): StakingUiState {
return prevState.copy(
confirmStakingState = prevState.confirmStakingState.copyWrapped(),
)
}
private fun StakingStates.ConfirmStakingState.copyWrapped(): StakingStates.ConfirmStakingState {
return if (this is StakingStates.ConfirmStakingState.Data) {
copy(
isPrimaryButtonEnabled = false,
innerState = StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.IN_PROGRESS,
)
} else {
this
}
}
}

View file

@ -10,14 +10,14 @@ import com.tangem.utils.transformer.Transformer
import kotlinx.collections.immutable.persistentListOf
@Suppress("UnusedPrivateMember")
internal class SetConfirmLoadingStateTransformer(
internal class SetConfirmStateLoadingTransformer(
private val yield: Yield,
) : Transformer<StakingUiState> {
override fun transform(prevState: StakingUiState): StakingUiState {
val possibleConfirmStakingState = prevState.confirmStakingState as? StakingStates.ConfirmStakingState.Data
val possibleValidatorState = possibleConfirmStakingState?.validatorState as? ValidatorState.Content
val chosenValidator = possibleValidatorState?.chosenValidator ?: yield.validators[0] // TODO staking add sorting
val chosenValidator = possibleValidatorState?.chosenValidator ?: yield.validators[0]
return prevState.copy(
confirmStakingState = StakingStates.ConfirmStakingState.Data(
@ -34,8 +34,7 @@ internal class SetConfirmLoadingStateTransformer(
),
),
footerText = "",
isSuccess = false,
isStaking = false, // TODO staking move to enum
innerState = StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.CONFIRM,
),
)
}

View file

@ -6,6 +6,8 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import arrow.core.getOrElse
import com.tangem.blockchain.common.TransactionData
import com.tangem.common.extensions.hexToBytes
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.bundle.unbundle
import com.tangem.common.ui.amountScreen.models.AmountState
@ -14,9 +16,11 @@ import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.staking.InitializeStakingProcessUseCase
import com.tangem.domain.staking.model.Yield
import com.tangem.domain.staking.model.transaction.StakingTransaction
import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
@ -24,6 +28,7 @@ import com.tangem.features.staking.impl.navigation.InnerStakingRouter
import com.tangem.features.staking.impl.presentation.state.*
import com.tangem.features.staking.impl.presentation.state.StakingStateController
import com.tangem.features.staking.impl.presentation.state.StakingStateRouter
import com.tangem.features.staking.impl.presentation.state.StakingStates
import com.tangem.features.staking.impl.presentation.state.StakingUiState
import com.tangem.features.staking.impl.presentation.state.transformers.*
import com.tangem.features.staking.impl.presentation.state.transformers.amount.AmountChangeStateTransformer
@ -36,6 +41,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
import kotlin.properties.Delegates
@ -49,6 +55,7 @@ internal class StakingViewModel @Inject constructor(
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val initializeStakingProcessUseCase: InitializeStakingProcessUseCase,
private val sendTransactionUseCase: SendTransactionUseCase,
savedStateHandle: SavedStateHandle,
) : ViewModel(), DefaultLifecycleObserver, StakingClickIntents {
@ -58,6 +65,8 @@ internal class StakingViewModel @Inject constructor(
var stakingStateRouter: StakingStateRouter by Delegates.notNull()
private set
private var stakingTransaction: StakingTransaction? = null
private val cryptoCurrencyId: CryptoCurrency.ID =
savedStateHandle.get<Bundle>(AppRoute.Staking.CRYPTO_CURRENCY_ID_KEY)
?.unbundle(CryptoCurrency.ID.serializer())
@ -88,16 +97,30 @@ internal class StakingViewModel @Inject constructor(
}
override fun onNextClick() {
handleOnNextConfirmClick()
stakingStateRouter.onNextClick()
if (value.currentStep == StakingStep.Confirm) {
initStaking()
}
}
private fun handleOnNextConfirmClick() {
if (value.currentStep == StakingStep.Confirm &&
(value.confirmStakingState as? StakingStates.ConfirmStakingState.Data)?.innerState ==
StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.CONFIRM
) {
viewModelScope.launch {
stakingTransaction?.unsignedTransaction?.let {
sendStakingTransaction(TransactionData.Compiled(value = it.hexToBytes()))
} ?: error("No unsigned transaction available")
}
}
}
private fun initStaking() {
viewModelScope.launch {
stateController.update(
SetConfirmLoadingStateTransformer(
SetConfirmStateLoadingTransformer(
yield = yield,
),
)
@ -111,14 +134,17 @@ internal class StakingViewModel @Inject constructor(
validatorAddress = yield.validators.getOrNull(0)?.address ?: error("No available validator"),
token = yield.token,
)
val (enterAction, stakingTransaction) = actionWithTransaction.getOrElse {
error("Can't retrieve action and transaction")
error(it)
}
this@StakingViewModel.stakingTransaction = stakingTransaction
val stakingGasEstimate = stakingTransaction.gasEstimate ?: error("Can't get fee info")
stateController.update(
SetConfirmStateDataStateTransformer(
SetConfirmStateConfirmTransformer(
appCurrencyProvider = Provider { appCurrency },
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
stakingGasEstimate = stakingGasEstimate,
@ -226,4 +252,42 @@ internal class StakingViewModel @Inject constructor(
.flowOn(dispatchers.main)
.launchIn(viewModelScope)
}
private suspend fun sendStakingTransaction(txData: TransactionData) {
stateController.update(SetConfirmStateInProgressTransformer())
sendTransactionUseCase(
txData = txData,
userWallet = userWallet,
network = cryptoCurrencyStatus.currency.network,
).fold(
ifLeft = { error ->
Timber.e(error.toString())
val gasEstimate = stakingTransaction?.gasEstimate ?: return@fold
stateController.update(
SetConfirmStateConfirmTransformer(
appCurrencyProvider = Provider { appCurrency },
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
stakingGasEstimate = gasEstimate,
),
)
// uiState = eventStateFactory.getSendTransactionErrorState(
// error = error,
// onConsume = { uiState = eventStateFactory.onConsumeEventState() },
// )
// analyticsEventHandler.send(SendAnalyticEvents.TransactionError(cryptoCurrency.symbol))
},
ifRight = {
val gasEstimate = stakingTransaction?.gasEstimate ?: return@fold
stateController.update(
SetConfirmStateConfirmTransformer(
appCurrencyProvider = Provider { appCurrency },
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
stakingGasEstimate = gasEstimate,
),
)
// sendScreenAnalyticSender.sendTransaction()
},
)
}
}