From 0391e50dc8c6d1d49854471ccb70d019744ffa08 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 16 Jul 2024 13:26:37 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/StakingDomainModule.kt | 18 ++++- .../datasource/api/stakekit/StakeKitApi.kt | 9 ++- ...ionRequestBody.kt => ActionRequestBody.kt} | 5 +- .../data/staking/DefaultStakingRepository.kt | 47 +++++++---- .../model/action/StakingActionCommonType.kt | 6 ++ .../staking/model/transaction/ActionParams.kt | 14 ++++ .../domain/staking/EstimateGasUseCase.kt | 25 ++++++ ...ase.kt => GetStakingTransactionUseCase.kt} | 24 ++---- .../staking/repositories/StakingRepository.kt | 14 ++-- .../repository/MockStakingRepository.kt | 59 +++++++++----- .../ui/StakingNavigationButtons.kt | 2 +- .../viewmodel/StakingViewModel.kt | 81 +++++++++++-------- 12 files changed, 198 insertions(+), 106 deletions(-) rename core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/{EnterActionRequestBody.kt => ActionRequestBody.kt} (87%) create mode 100644 domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/StakingActionCommonType.kt create mode 100644 domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/transaction/ActionParams.kt create mode 100644 domain/staking/src/main/java/com/tangem/domain/staking/EstimateGasUseCase.kt rename domain/staking/src/main/java/com/tangem/domain/staking/{InitializeStakingProcessUseCase.kt => GetStakingTransactionUseCase.kt} (62%) 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 f080165fe4..10f1264ba6 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 @@ -87,11 +87,23 @@ internal object StakingDomainModule { @Provides @Singleton - fun provideCreateEnterActionUseCase( + fun provideInitializeStakingProcessUseCase( stakingRepository: StakingRepository, stakingErrorResolver: StakingErrorResolver, - ): InitializeStakingProcessUseCase { - return InitializeStakingProcessUseCase( + ): GetStakingTransactionUseCase { + return GetStakingTransactionUseCase( + stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, + ) + } + + @Provides + @Singleton + fun provideGasEstimateUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): EstimateGasUseCase { + return EstimateGasUseCase( stakingRepository = stakingRepository, stakingErrorResolver = stakingErrorResolver, ) 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 17e656903f..fc7dab4bd6 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 @@ -9,6 +9,7 @@ import com.tangem.datasource.api.stakekit.models.response.model.transaction.Stak 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.transaction.StakingGasEstimateDTO import retrofit2.http.* @Suppress("LongParameterList") @@ -45,7 +46,13 @@ interface StakeKitApi { suspend fun getTokens(): ApiResponse> @POST("actions/enter") - suspend fun createEnterAction(@Body body: EnterActionRequestBody): ApiResponse + suspend fun createEnterAction(@Body body: ActionRequestBody): ApiResponse + + @POST("actions/enter/estimate-gas") + suspend fun estimateGasOnEnter(@Body body: ActionRequestBody): ApiResponse + + @POST("actions/exit/estimate-gas") + suspend fun estimateGasOnExit(@Body body: ActionRequestBody): ApiResponse @PATCH("transactions/{transactionId}") suspend fun constructTransaction( diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/EnterActionRequestBody.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/ActionRequestBody.kt similarity index 87% rename from core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/EnterActionRequestBody.kt rename to core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/ActionRequestBody.kt index 6d06f46f5c..e044b1f9a9 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/EnterActionRequestBody.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/ActionRequestBody.kt @@ -1,10 +1,11 @@ package com.tangem.datasource.api.stakekit.models.request import com.squareup.moshi.Json +import com.tangem.datasource.api.stakekit.models.request.ConstructTransactionRequestBody.GasArgs import com.tangem.datasource.api.stakekit.models.response.model.BalanceDTO import com.tangem.datasource.api.stakekit.models.response.model.TokenDTO -data class EnterActionRequestBody( +data class ActionRequestBody( @Json(name = "integrationId") val integrationId: String, @Json(name = "addresses") @@ -13,6 +14,8 @@ data class EnterActionRequestBody( val args: EnterActionRequestBodyArgs, @Json(name = "referralCode") val referralCode: String? = null, + @Json(name = "gasArgs") + val gasArgs: GasArgs? = null, // used only in estimate_gas request ) { data class EnterActionRequestBodyArgs( 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 c9c22d3596..5249e59c74 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 @@ -25,6 +25,9 @@ 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.StakingActionCommonType +import com.tangem.domain.staking.model.transaction.StakingGasEstimate +import com.tangem.domain.staking.model.transaction.ActionParams import com.tangem.domain.staking.model.transaction.StakingTransaction import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.model.CryptoCurrency @@ -37,7 +40,6 @@ import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.math.BigDecimal @Suppress("LargeClass", "LongParameterList") internal class DefaultStakingRepository( @@ -153,29 +155,28 @@ internal class DefaultStakingRepository( } } - override suspend fun createEnterAction( - integrationId: String, - amount: BigDecimal, - address: String, - validatorAddress: String, - token: Token, - ): EnterAction { + override suspend fun createEnterAction(params: ActionParams): EnterAction { return withContext(dispatchers.io) { - val body = EnterActionRequestBody( - integrationId = integrationId, - addresses = Address(address), - args = EnterActionRequestBody.EnterActionRequestBodyArgs( - amount = amount.toFormattedString(token.decimals), - inputToken = tokenConverter.convertBack(token), - validatorAddress = validatorAddress, - ), - ) + val body = createActionRequestBody(params) val response = stakeKitApi.createEnterAction(body) enterActionResponseConverter.convert(response.getOrThrow()) } } + override suspend fun estimateGas(params: ActionParams): StakingGasEstimate { + return withContext(dispatchers.io) { + val body = createActionRequestBody(params) + + val gasEstimateDTO = when (params.actionCommonType) { + StakingActionCommonType.ENTER -> stakeKitApi.estimateGasOnEnter(body) + StakingActionCommonType.EXIT -> stakeKitApi.estimateGasOnExit(body) + } + + gasEstimateConverter.convert(gasEstimateDTO.getOrThrow()) + } + } + override suspend fun constructTransaction(transactionId: String): StakingTransaction { return withContext(dispatchers.io) { val transactionResponse = stakeKitApi.constructTransaction( @@ -423,6 +424,18 @@ internal class DefaultStakingRepository( } } + private fun createActionRequestBody(params: ActionParams): ActionRequestBody { + return ActionRequestBody( + integrationId = params.integrationId, + addresses = Address(params.address), + args = ActionRequestBody.EnterActionRequestBodyArgs( + amount = params.amount.toFormattedString(params.token.decimals), + inputToken = tokenConverter.convertBack(params.token), + validatorAddress = params.validatorAddress, + ), + ) + } + private fun findPrefetchedYield(yields: List, currencyId: String, symbol: String): Yield? { return yields.find { it.token.coinGeckoId == currencyId && it.token.symbol == symbol } } diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/StakingActionCommonType.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/StakingActionCommonType.kt new file mode 100644 index 0000000000..59f5e782d9 --- /dev/null +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/action/StakingActionCommonType.kt @@ -0,0 +1,6 @@ +package com.tangem.domain.staking.model.action + +enum class StakingActionCommonType { + ENTER, + EXIT, +} \ No newline at end of file diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/transaction/ActionParams.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/transaction/ActionParams.kt new file mode 100644 index 0000000000..ab5aa8f530 --- /dev/null +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/transaction/ActionParams.kt @@ -0,0 +1,14 @@ +package com.tangem.domain.staking.model.transaction + +import com.tangem.domain.staking.model.Token +import com.tangem.domain.staking.model.action.StakingActionCommonType +import java.math.BigDecimal + +data class ActionParams( + val actionCommonType: StakingActionCommonType, + val integrationId: String, + val amount: BigDecimal, + val address: String, + val validatorAddress: String, + val token: Token, +) \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/EstimateGasUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/EstimateGasUseCase.kt new file mode 100644 index 0000000000..bbbac8f73f --- /dev/null +++ b/domain/staking/src/main/java/com/tangem/domain/staking/EstimateGasUseCase.kt @@ -0,0 +1,25 @@ +package com.tangem.domain.staking + +import arrow.core.Either +import com.tangem.domain.staking.model.StakingError +import com.tangem.domain.staking.model.transaction.ActionParams +import com.tangem.domain.staking.model.transaction.StakingGasEstimate +import com.tangem.domain.staking.repositories.StakingErrorResolver +import com.tangem.domain.staking.repositories.StakingRepository + +/** + * Use case for staking gas estimation. + */ +class EstimateGasUseCase( + private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, +) { + + suspend operator fun invoke(params: ActionParams): Either { + return Either.catch { + stakingRepository.estimateGas(params) + }.mapLeft { + stakingErrorResolver.resolve(it) + } + } +} \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/InitializeStakingProcessUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingTransactionUseCase.kt similarity index 62% rename from domain/staking/src/main/java/com/tangem/domain/staking/InitializeStakingProcessUseCase.kt rename to domain/staking/src/main/java/com/tangem/domain/staking/GetStakingTransactionUseCase.kt index 4a9fc87c47..12107bff68 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/InitializeStakingProcessUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingTransactionUseCase.kt @@ -2,37 +2,23 @@ package com.tangem.domain.staking import arrow.core.Either import com.tangem.domain.staking.model.StakingError -import com.tangem.domain.staking.model.Token -import com.tangem.domain.staking.model.action.EnterAction +import com.tangem.domain.staking.model.transaction.ActionParams import com.tangem.domain.staking.model.transaction.StakingTransaction import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository import kotlinx.coroutines.delay -import java.math.BigDecimal /** * Use case for creating enter action */ -class InitializeStakingProcessUseCase( +class GetStakingTransactionUseCase( private val stakingRepository: StakingRepository, private val stakingErrorResolver: StakingErrorResolver, ) { - suspend operator fun invoke( - integrationId: String, - amount: BigDecimal, - address: String, - validatorAddress: String, - token: Token, - ): Either> { + suspend operator fun invoke(params: ActionParams): Either { return Either.catch { - val createAction = stakingRepository.createEnterAction( - integrationId = integrationId, - amount = amount, - address = address, - validatorAddress = validatorAddress, - token = token, - ) + val createAction = stakingRepository.createEnterAction(params) // workaround, sometimes transaction is not created immediately after actions/enter delay(PATCH_TRANSACTION_REQUEST_DELAY) @@ -40,7 +26,7 @@ class InitializeStakingProcessUseCase( val createdTransaction = createAction.transactions?.get(0) ?: error("No available transaction to patch") val patchedTransaction = stakingRepository.constructTransaction(createdTransaction.id) - createAction to patchedTransaction + patchedTransaction }.mapLeft { stakingErrorResolver.resolve(it) } 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 8b74784341..3776a2e27b 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 @@ -2,13 +2,13 @@ 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.Token import com.tangem.domain.staking.model.Yield import com.tangem.domain.staking.model.action.EnterAction import com.tangem.domain.staking.model.transaction.StakingTransaction -import java.math.BigDecimal 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.transaction.ActionParams import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyAddress import com.tangem.domain.wallets.models.UserWalletId @@ -60,13 +60,9 @@ interface StakingRepository { addresses: List, ): YieldBalanceList - suspend fun createEnterAction( - integrationId: String, - amount: BigDecimal, - address: String, - validatorAddress: String, - token: Token, - ): EnterAction + suspend fun createEnterAction(params: ActionParams): EnterAction + + suspend fun estimateGas(params: ActionParams): StakingGasEstimate suspend fun constructTransaction(transactionId: String): StakingTransaction 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 074c07f027..1c27d431af 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 @@ -6,9 +6,7 @@ import com.tangem.domain.staking.model.* import com.tangem.domain.staking.model.action.EnterAction import com.tangem.domain.staking.model.action.StakingActionStatus import com.tangem.domain.staking.model.action.StakingActionType -import com.tangem.domain.staking.model.transaction.StakingTransaction -import com.tangem.domain.staking.model.transaction.StakingTransactionStatus -import com.tangem.domain.staking.model.transaction.StakingTransactionType +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 @@ -21,7 +19,8 @@ import java.math.BigDecimal class MockStakingRepository : StakingRepository { override fun isStakingSupported(currencyId: String): Boolean = true - override suspend fun fetchEnabledYields(refresh: Boolean) { /* no-op */ + override suspend fun fetchEnabledYields(refresh: Boolean) { + /* no-op */ } override suspend fun getEntryInfo(integrationId: String): StakingEntryInfo = StakingEntryInfo( @@ -165,24 +164,37 @@ class MockStakingRepository : StakingRepository { balances = listOf(YieldBalance.Error), ) - override suspend fun createEnterAction( - integrationId: String, - amount: BigDecimal, - address: String, - validatorAddress: String, - token: Token, - ): EnterAction = EnterAction( - id = "quis", - integrationId = "persequeris", - status = StakingActionStatus.PROCESSING, - type = StakingActionType.CLAIM_REWARDS, - currentStepIndex = 8701, - amount = BigDecimal.ZERO, - validatorAddress = null, - validatorAddresses = listOf(), - transactions = listOf(), - createdAt = DateTime.now(), - ) + override suspend fun createEnterAction(params: ActionParams): EnterAction { + return EnterAction( + id = "quis", + integrationId = "persequeris", + status = StakingActionStatus.PROCESSING, + type = StakingActionType.CLAIM_REWARDS, + currentStepIndex = 8701, + amount = BigDecimal.ZERO, + validatorAddress = null, + validatorAddresses = listOf(), + transactions = listOf(), + createdAt = DateTime.now(), + ) + } + + override suspend fun estimateGas(params: ActionParams): StakingGasEstimate { + return StakingGasEstimate( + amount = BigDecimal(0.0001), + token = Token( + name = "Solana", + network = NetworkType.SOLANA, + symbol = "SOL", + decimals = 18, + address = null, + coinGeckoId = "solana", + logoURI = null, + isPoints = null, + ), + gasLimit = null, + ) + } override suspend fun constructTransaction(transactionId: String): StakingTransaction = StakingTransaction( id = "id", @@ -202,11 +214,14 @@ class MockStakingRepository : StakingRepository { ) override suspend fun submitHash(transactionId: String, transactionHash: String) { + /* no-op */ } override suspend fun storeUnsubmittedHash(unsubmittedTransactionMetadata: UnsubmittedTransactionMetadata) { + /* no-op */ } override suspend fun sendUnsubmittedHashes() { + /* no-op */ } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingNavigationButtons.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingNavigationButtons.kt index 695d1a3bb7..73e2c6e526 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingNavigationButtons.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingNavigationButtons.kt @@ -113,7 +113,7 @@ private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier if (showTangemIcon) hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) if (buttonClick != null) buttonClick() }, - showProgress = false, + showProgress = isInProgressInnerState, modifier = Modifier.fillMaxWidth(), colors = TangemButtonsDefaults.primaryButtonColors, ) 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 77a9005b01..5549b2dbf0 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 @@ -14,11 +14,14 @@ import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase -import com.tangem.domain.staking.InitializeStakingProcessUseCase +import com.tangem.domain.staking.GetStakingTransactionUseCase +import com.tangem.domain.staking.EstimateGasUseCase import com.tangem.domain.staking.SaveUnsubmittedHashUseCase import com.tangem.domain.staking.SubmitHashUseCase import com.tangem.domain.staking.model.Yield -import com.tangem.domain.staking.model.transaction.StakingTransaction +import com.tangem.domain.staking.model.action.StakingActionCommonType +import com.tangem.domain.staking.model.transaction.ActionParams +import com.tangem.domain.staking.model.transaction.StakingGasEstimate import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus @@ -57,7 +60,8 @@ internal class StakingViewModel @Inject constructor( private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, - private val initializeStakingProcessUseCase: InitializeStakingProcessUseCase, + private val getStakingTransactionUseCase: GetStakingTransactionUseCase, + private val estimateGasUseCase: EstimateGasUseCase, private val sendTransactionUseCase: SendTransactionUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val saveUnsubmittedHashUseCase: SaveUnsubmittedHashUseCase, @@ -71,8 +75,6 @@ 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(AppRoute.Staking.CRYPTO_CURRENCY_ID_KEY) ?.unbundle(CryptoCurrency.ID.serializer()) @@ -113,8 +115,29 @@ internal class StakingViewModel @Inject constructor( private fun handleOnNextConfirmationClick() { if (isAssentState()) { viewModelScope.launch { - stakingTransaction?.unsignedTransaction?.let { - sendStakingTransaction(TransactionData.Compiled(value = it.hexToBytes())) + stateController.update(SetConfirmationStateInProgressTransformer()) + + val stakingTransaction = getStakingTransactionUseCase( + params = ActionParams( + actionCommonType = StakingActionCommonType.ENTER, + integrationId = yield.id, + amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value + ?: error("No amount provided"), + address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value + ?: error("No available address"), + validatorAddress = yield.validators.getOrNull(0)?.address ?: error("No available validator"), + token = yield.token, + ), + ).getOrElse { + error(it) + } + + stakingTransaction.unsignedTransaction?.let { + sendStakingTransaction( + transactionId = stakingTransaction.id, + gasEstimate = stakingTransaction.gasEstimate ?: error("No gas estimate available"), + TransactionData.Compiled(value = it.hexToBytes()), + ) } ?: error("No unsigned transaction available") } } @@ -128,23 +151,18 @@ internal class StakingViewModel @Inject constructor( ), ) - val actionWithTransaction = initializeStakingProcessUseCase( - integrationId = yield.id, - amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value - ?: error("No amount provided"), - address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value - ?: error("No available address"), - validatorAddress = yield.validators.getOrNull(0)?.address ?: error("No available validator"), - token = yield.token, - ) - - val (enterAction, stakingTransaction) = actionWithTransaction.getOrElse { - error(it) - } - - this@StakingViewModel.stakingTransaction = stakingTransaction - - val stakingGasEstimate = stakingTransaction.gasEstimate ?: error("Can't get fee info") + val stakingGasEstimate = estimateGasUseCase( + params = ActionParams( + actionCommonType = StakingActionCommonType.ENTER, + integrationId = yield.id, + amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value + ?: error("No amount provided"), + address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value + ?: error("No available address"), + validatorAddress = yield.validators.getOrNull(0)?.address ?: error("No available validator"), + token = yield.token, + ), + ).getOrElse { error("Can't get fee info") } stateController.update( SetConfirmationStateAssentTransformer( @@ -270,9 +288,11 @@ internal class StakingViewModel @Inject constructor( .launchIn(viewModelScope) } - private suspend fun sendStakingTransaction(txData: TransactionData) { - stateController.update(SetConfirmationStateInProgressTransformer()) - + private suspend fun sendStakingTransaction( + transactionId: String, + gasEstimate: StakingGasEstimate, + txData: TransactionData, + ) { sendTransactionUseCase( txData = txData, userWallet = userWallet, @@ -280,7 +300,6 @@ internal class StakingViewModel @Inject constructor( ).fold( ifLeft = { error -> Timber.e(error.toString()) - val gasEstimate = stakingTransaction?.gasEstimate ?: return@fold stateController.update( SetConfirmationStateAssentTransformer( appCurrencyProvider = Provider { appCurrency }, @@ -290,17 +309,13 @@ internal class StakingViewModel @Inject constructor( ) }, ifRight = { txHash -> - val transaction = stakingTransaction ?: return@fold - - submitHash(transaction.id, txHash) + submitHash(transactionId, txHash) val txUrl = getExplorerTransactionUrlUseCase( txHash = txHash, networkId = cryptoCurrencyStatus.currency.network.id, ).getOrElse { "" } - val gasEstimate = transaction.gasEstimate ?: error("No gas for transaction") - stateController.update( SetConfirmationStateCompletedTransformer( appCurrencyProvider = Provider { appCurrency },