From 75f8a45cd40e1ce7839f393bbf681123686365a4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 15 Jul 2024 17:27:27 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 2 +- .../tap/di/domain/StakingDomainModule.kt | 85 +++++++++-- .../tangem/tap/features/main/MainViewModel.kt | 2 +- .../model/error/StakeKitErrorResponse.kt | 143 ++++++++++++++++++ .../staking/DefaultStakingErrorResolver.kt | 19 +++ .../error/StakeKitErrorConverter.kt | 108 +++++++++++++ .../data/staking/di/StakingDataModule.kt | 15 ++ .../domain/staking/model/StakingError.kt | 92 +++++++++++ .../staking/FetchStakingTokensUseCase.kt | 8 +- .../FetchStakingYieldBalanceUseCase.kt | 24 ++- .../staking/GetStakingAvailabilityUseCase.kt | 14 +- .../staking/GetStakingEntryInfoUseCase.kt | 13 +- .../staking/GetStakingYieldBalanceUseCase.kt | 9 +- .../tangem/domain/staking/GetYieldUseCase.kt | 14 +- .../InitializeStakingProcessUseCase.kt | 11 +- .../staking/SaveUnsubmittedHashUseCase.kt | 11 +- .../staking/SendUnsubmittedHashesUseCase.kt | 15 +- .../domain/staking/SubmitHashUseCase.kt | 24 ++- .../staking/error/StakingTokensError.kt | 6 - .../repositories/StakingErrorResolver.kt | 8 + .../state/factory/TokenDetailsStateFactory.kt | 3 +- .../factory/TokenStakingStateConverter.kt | 5 +- .../viewmodels/TokenDetailsViewModel.kt | 3 +- 23 files changed, 569 insertions(+), 65 deletions(-) create mode 100644 core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/error/StakeKitErrorResponse.kt create mode 100644 data/staking/src/main/java/com/tangem/data/staking/DefaultStakingErrorResolver.kt create mode 100644 data/staking/src/main/java/com/tangem/data/staking/converters/error/StakeKitErrorConverter.kt create mode 100644 domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingError.kt delete mode 100644 domain/staking/src/main/java/com/tangem/domain/staking/error/StakingTokensError.kt create mode 100644 domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingErrorResolver.kt diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 2708e92fb4..2c3936c358 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -594,7 +594,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac lifecycleScope.launch { sendUnsubmittedHashesUseCase.invoke() .onRight { Timber.d("Submitting hashes succeeded") } - .onLeft { Timber.e(it) } + .onLeft { Timber.e(it.toString()) } } } } \ No newline at end of file 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 49ee51f726..f080165fe4 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 @@ -1,6 +1,7 @@ package com.tangem.tap.di.domain import com.tangem.domain.staking.* +import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository import dagger.Module import dagger.Provides @@ -14,69 +15,121 @@ internal object StakingDomainModule { @Provides @Singleton - fun provideGetStakingAvailabilityUseCase(stakingRepository: StakingRepository): GetStakingAvailabilityUseCase { + fun provideGetStakingAvailabilityUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): GetStakingAvailabilityUseCase { return GetStakingAvailabilityUseCase( stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, ) } @Provides @Singleton - fun provideGetStakingEntryInfoUseCase(stakingRepository: StakingRepository): GetStakingEntryInfoUseCase { + fun provideGetStakingEntryInfoUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): GetStakingEntryInfoUseCase { return GetStakingEntryInfoUseCase( stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, ) } @Provides @Singleton - fun provideGetYieldUseCase(stakingRepository: StakingRepository): GetYieldUseCase { + fun provideGetYieldUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): GetYieldUseCase { return GetYieldUseCase( stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, ) } @Provides @Singleton - fun provideGetStakingTokensUseCase(stakingRepository: StakingRepository): FetchStakingTokensUseCase { + fun provideGetStakingTokensUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): FetchStakingTokensUseCase { return FetchStakingTokensUseCase( stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, ) } @Provides @Singleton - fun provideFetchStakingYieldBalanceUseCase(stakingRepository: StakingRepository): FetchStakingYieldBalanceUseCase { - return FetchStakingYieldBalanceUseCase(stakingRepository = stakingRepository) + fun provideFetchStakingYieldBalanceUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): FetchStakingYieldBalanceUseCase { + return FetchStakingYieldBalanceUseCase( + stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, + ) } @Provides @Singleton - fun provideGetStakingYieldBalanceUseCase(stakingRepository: StakingRepository): GetStakingYieldBalanceUseCase { - return GetStakingYieldBalanceUseCase(stakingRepository = stakingRepository) + fun provideGetStakingYieldBalanceUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): GetStakingYieldBalanceUseCase { + return GetStakingYieldBalanceUseCase( + stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, + ) } @Provides @Singleton - fun provideCreateEnterActionUseCase(stakingRepository: StakingRepository): InitializeStakingProcessUseCase { - return InitializeStakingProcessUseCase(stakingRepository) + fun provideCreateEnterActionUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): InitializeStakingProcessUseCase { + return InitializeStakingProcessUseCase( + stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, + ) } @Provides @Singleton - fun provideSubmitHashUseCase(stakingRepository: StakingRepository): SubmitHashUseCase { - return SubmitHashUseCase(stakingRepository) + fun provideSubmitHashUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): SubmitHashUseCase { + return SubmitHashUseCase( + stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, + ) } @Provides @Singleton - fun provideSaveUnsubmittedHashUseCase(stakingRepository: StakingRepository): SaveUnsubmittedHashUseCase { - return SaveUnsubmittedHashUseCase(stakingRepository) + fun provideSaveUnsubmittedHashUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): SaveUnsubmittedHashUseCase { + return SaveUnsubmittedHashUseCase( + stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, + ) } @Provides @Singleton - fun provideSendUnsubmittedHashesUseCase(stakingRepository: StakingRepository): SendUnsubmittedHashesUseCase { - return SendUnsubmittedHashesUseCase(stakingRepository) + fun provideSendUnsubmittedHashesUseCase( + stakingRepository: StakingRepository, + stakingErrorResolver: StakingErrorResolver, + ): SendUnsubmittedHashesUseCase { + return SendUnsubmittedHashesUseCase( + stakingRepository = stakingRepository, + stakingErrorResolver = stakingErrorResolver, + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt index b127b60b18..fd2b740b37 100644 --- a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt @@ -125,7 +125,7 @@ internal class MainViewModel @Inject constructor( private fun fetchStakingTokens() { viewModelScope.launch(dispatchers.main) { fetchStakingTokensUseCase() - .onLeft { Timber.e(it, "Unable to fetch the staking tokens list") } + .onLeft { Timber.e(it.toString(), "Unable to fetch the staking tokens list") } .onRight { Timber.d("Staking token list was fetched successfully") } } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/error/StakeKitErrorResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/error/StakeKitErrorResponse.kt new file mode 100644 index 0000000000..cf62a7d43b --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/error/StakeKitErrorResponse.kt @@ -0,0 +1,143 @@ +package com.tangem.datasource.api.stakekit.models.response.model.error + +import com.squareup.moshi.Json + +class StakeKitErrorResponse( + @Json(name = "details") + val details: StakeKitErrorDetailsDTO? = null, + @Json(name = "message") + val message: StakeKitErrorMessageDTO? = null, + @Json(name = "level") + val level: String? = null, // unused +) + +data class StakeKitErrorDetailsDTO( + @Json(name = "arguments") + val arguments: String? = null, + @Json(name = "amount") + val amount: String? = null, + @Json(name = "yieldId") + val yieldId: String? = null, +) + +enum class StakeKitErrorMessageDTO { + @Json(name = "MissingArgumentsError") + MISSING_ARGUMENTS_ERROR, + + @Json(name = "MinimumAmountNotReached") + MINIMUM_AMOUNT_NOT_REACHED, + + @Json(name = "YieldUnderMaintenanceError") + YIELD_UNDER_MAINTENANCE_ERROR, + + @Json(name = "InsufficientFundsError") + INSUFFICIENT_FUNDS_ERROR, + + @Json(name = "StakedPositionNotFoundError") + STAKED_POSITION_NOT_FOUND_ERROR, + + @Json(name = "InvalidAmountSubmittedError") + INVALID_AMOUNT_SUBMITTED_ERROR, + + @Json(name = "BalanceUnavailableError") + BALANCE_UNAVAILABLE_ERROR, + + @Json(name = "GasPriceUnavailableError") + GAS_PRICE_UNAVAILABLE_ERROR, + + @Json(name = "NotImplementedError") + NOT_IMPLEMENTED_ERROR, + + @Json(name = "TokenNotFoundError") + TOKEN_NOT_FOUND_ERROR, + + @Json(name = "BroadcastTransactionError") + BROADCAST_TRANSACTION_ERROR, + + @Json(name = "MissingGasPriceStrategyError") + MISSING_GAS_PRICE_STRATEGY_ERROR, + + @Json(name = "SubstrateMalformedTransactionHashError") + SUBSTRATE_MALFORMED_TRANSACTION_HASH_ERROR, + + @Json(name = "TronMaximumAmountOfValidatorsExceededError") + TRON_MAXIMUM_AMOUNT_OF_VALIDATORS_EXCEEDED_ERROR, + + @Json(name = "SubstratePoolNotFoundError") + SUBSTRATE_POOL_NOT_FOUND_ERROR, + + @Json(name = "SubstrateBondedAmountTooLowError") + SUBSTRATE_BONDED_AMOUNT_TOO_LOW_ERROR, + + @Json(name = "TronMissingResourceTypeArgumentError") + TRON_MISSING_RESOURCE_TYPE_ARGUMENT_ERROR, + + @Json(name = "AaveV3PoolFrozenError") + AAVE_V3_POOL_FROZEN_ERROR, + + @Json(name = "AaveV3TokenPairNotFoundError") + AAVE_V3_TOKEN_PAIR_NOT_FOUND_ERROR, + + @Json(name = "YearnVaultAtMaxCapacityError") + YEARN_VAULT_AT_MAX_CAPACITY_ERROR, + + @Json(name = "StETHNoWithdrawalRequestsFoundError") + STETH_NO_WITHDRAWAL_REQUESTS_FOUND_ERROR, + + @Json(name = "MorphoLendingPoolPausedError") + MORPHO_LENDING_POOL_PAUSED_ERROR, + + @Json(name = "NonceUnavailableError") + NONCE_UNAVAILABLE_ERROR, + + @Json(name = "CosmosAcccountNotFoundError") + COSMOS_ACCOUNT_NOT_FOUND_ERROR, + + @Json(name = "AvalancheMissingAdditionalAddressesArgumentError") + AVALANCHE_MISSING_ADDITIONAL_ADDRESSES_ARGUMENT_ERROR, + + @Json(name = "AvalancheValidatorInfoNotFoundError") + AVALANCHE_VALIDATOR_INFO_NOT_FOUND_ERROR, + + @Json(name = "SolanaTransactionSignatureVerificationFailureError") + SOLANA_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE_ERROR, + + @Json(name = "SolanaUnableTocreateStakeAccountError") + SOLANA_UNABLE_TO_CREATE_STAKE_ACCOUNT_ERROR, + + @Json(name = "SolanaStakeAmountTooLowError") + SOLANA_STAKE_AMOUNT_TOO_LOW_ERROR, + + @Json(name = "SolanaUnstakeAmountTooLowError") + SOLANA_UNSTAKE_AMOUNT_TOO_LOW_ERROR, + + @Json(name = "SolanaStakeAccountsNotFoundError") + SOLANA_STAKE_ACCOUNTS_NOT_FOUND_ERROR, + + @Json(name = "SolanaEligibleStakeAccountsNotFoundError") + SOLANA_ELIGIBLE_STAKE_ACCOUNTS_NOT_FOUND_ERROR, + + @Json(name = "TezosNoBalanceDelegatedError") + TEZOS_NO_BALANCE_DELEGATED_ERROR, + + @Json(name = "TezosMissingPubkeyArgumentError") + TEZOS_MISSING_PUBKEY_ARGUMENT_ERROR, + + @Json(name = "TezosEstimateRevealGasLimitError") + TEZOS_ESTIMATE_REVEAL_GAS_LIMIT_ERROR, + + @Json(name = "TezosBalanceAlreadyDelegatedError") + TEZOS_BALANCE_ALREADY_DELEGATED_ERROR, + + @Json(name = "BinanceAccountNotFoundError") + BINANCE_ACCOUNT_NOT_FOUND_ERROR, + + @Json(name = "BinanceMissingAccountNumberOrSequenceError") + BINANCE_MISSING_ACCOUNT_NUMBER_OR_SEQUENCE_ERROR, + + @Json(name = "GRTStakingDisabledError") + GRT_STAKING_DISABLED_ERROR, + + @Json(name = "GRTStakingDisabledLedgerLiveError") + GRT_STAKING_DISABLED_LEDGER_LIVE_ERROR, +} \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingErrorResolver.kt b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingErrorResolver.kt new file mode 100644 index 0000000000..8fed7f5841 --- /dev/null +++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingErrorResolver.kt @@ -0,0 +1,19 @@ +package com.tangem.data.staking + +import com.tangem.data.staking.converters.error.StakeKitErrorConverter +import com.tangem.datasource.api.common.response.ApiResponseError +import com.tangem.domain.staking.model.StakingError +import com.tangem.domain.staking.repositories.StakingErrorResolver + +internal class DefaultStakingErrorResolver( + private val stakeKitErrorConverter: StakeKitErrorConverter, +) : StakingErrorResolver { + + override fun resolve(throwable: Throwable): StakingError { + return if (throwable is ApiResponseError.HttpException) { + stakeKitErrorConverter.convert(throwable.errorBody.orEmpty()) + } else { + StakingError.UnknownError + } + } +} \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/converters/error/StakeKitErrorConverter.kt b/data/staking/src/main/java/com/tangem/data/staking/converters/error/StakeKitErrorConverter.kt new file mode 100644 index 0000000000..30020c0708 --- /dev/null +++ b/data/staking/src/main/java/com/tangem/data/staking/converters/error/StakeKitErrorConverter.kt @@ -0,0 +1,108 @@ +package com.tangem.data.staking.converters.error + +import com.squareup.moshi.JsonAdapter +import com.tangem.datasource.api.stakekit.models.response.model.error.StakeKitErrorMessageDTO +import com.tangem.datasource.api.stakekit.models.response.model.error.StakeKitErrorResponse +import com.tangem.domain.staking.model.StakingError +import com.tangem.utils.converter.Converter + +internal class StakeKitErrorConverter( + private val jsonAdapter: JsonAdapter, +) : Converter { + + @Suppress("CyclomaticComplexMethod", "LongMethod") + override fun convert(value: String): StakingError { + return try { + val stakeKitErrorResponse = jsonAdapter.fromJson(value) ?: return StakingError.UnknownError + + when (stakeKitErrorResponse.message) { + StakeKitErrorMessageDTO.MINIMUM_AMOUNT_NOT_REACHED -> StakingError.MinimumAmountNotReachedError( + amount = stakeKitErrorResponse.details?.amount ?: "", + ) + StakeKitErrorMessageDTO.MISSING_ARGUMENTS_ERROR -> StakingError.MissingArgumentsError( + arguments = stakeKitErrorResponse.details?.arguments ?: "", + ) + StakeKitErrorMessageDTO.YIELD_UNDER_MAINTENANCE_ERROR -> StakingError.YieldUnderMaintenanceError( + yieldId = stakeKitErrorResponse.details?.yieldId ?: "", + ) + StakeKitErrorMessageDTO.INSUFFICIENT_FUNDS_ERROR -> + StakingError.InsufficientFundsError + StakeKitErrorMessageDTO.STAKED_POSITION_NOT_FOUND_ERROR -> + StakingError.StakedPositionNotFoundError + StakeKitErrorMessageDTO.INVALID_AMOUNT_SUBMITTED_ERROR -> + StakingError.InvalidAmountSubmittedError + StakeKitErrorMessageDTO.BALANCE_UNAVAILABLE_ERROR -> + StakingError.BalanceUnavailableError + StakeKitErrorMessageDTO.GAS_PRICE_UNAVAILABLE_ERROR -> + StakingError.GasPriceUnavailableError + StakeKitErrorMessageDTO.NOT_IMPLEMENTED_ERROR -> + StakingError.NotImplementedError + StakeKitErrorMessageDTO.TOKEN_NOT_FOUND_ERROR -> + StakingError.TokenNotFoundError + StakeKitErrorMessageDTO.BROADCAST_TRANSACTION_ERROR -> + StakingError.BroadcastTransactionError + StakeKitErrorMessageDTO.MISSING_GAS_PRICE_STRATEGY_ERROR -> + StakingError.MissingGasPriceStrategyError + StakeKitErrorMessageDTO.SUBSTRATE_MALFORMED_TRANSACTION_HASH_ERROR -> + StakingError.SubstrateMalformedTransactionHashError + StakeKitErrorMessageDTO.TRON_MAXIMUM_AMOUNT_OF_VALIDATORS_EXCEEDED_ERROR -> + StakingError.TronMaximumAmountOfValidatorsExceededError + StakeKitErrorMessageDTO.SUBSTRATE_POOL_NOT_FOUND_ERROR -> + StakingError.SubstratePoolNotFoundError + StakeKitErrorMessageDTO.SUBSTRATE_BONDED_AMOUNT_TOO_LOW_ERROR -> + StakingError.SubstrateBondedAmountTooLowError + StakeKitErrorMessageDTO.TRON_MISSING_RESOURCE_TYPE_ARGUMENT_ERROR -> + StakingError.TronMissingResourceTypeArgumentError + StakeKitErrorMessageDTO.AAVE_V3_POOL_FROZEN_ERROR -> + StakingError.AaveV3PoolFrozenError + StakeKitErrorMessageDTO.AAVE_V3_TOKEN_PAIR_NOT_FOUND_ERROR -> + StakingError.AaveV3TokenPairNotFoundError + StakeKitErrorMessageDTO.YEARN_VAULT_AT_MAX_CAPACITY_ERROR -> + StakingError.YearnVaultAtMaxCapacityError + StakeKitErrorMessageDTO.STETH_NO_WITHDRAWAL_REQUESTS_FOUND_ERROR -> + StakingError.StETHNoWithdrawalRequestsFoundError + StakeKitErrorMessageDTO.MORPHO_LENDING_POOL_PAUSED_ERROR -> + StakingError.MorphoLendingPoolPausedError + StakeKitErrorMessageDTO.NONCE_UNAVAILABLE_ERROR -> + StakingError.NonceUnavailableError + StakeKitErrorMessageDTO.COSMOS_ACCOUNT_NOT_FOUND_ERROR -> + StakingError.CosmosAcccountNotFoundError + StakeKitErrorMessageDTO.AVALANCHE_MISSING_ADDITIONAL_ADDRESSES_ARGUMENT_ERROR -> + StakingError.AvalancheMissingAdditionalAddressesArgumentError + StakeKitErrorMessageDTO.AVALANCHE_VALIDATOR_INFO_NOT_FOUND_ERROR -> + StakingError.AvalancheValidatorInfoNotFoundError + StakeKitErrorMessageDTO.SOLANA_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE_ERROR -> + StakingError.SolanaTransactionSignatureVerificationFailureError + StakeKitErrorMessageDTO.SOLANA_UNABLE_TO_CREATE_STAKE_ACCOUNT_ERROR -> + StakingError.SolanaUnableTocreateStakeAccountError + StakeKitErrorMessageDTO.SOLANA_STAKE_AMOUNT_TOO_LOW_ERROR -> + StakingError.SolanaStakeAmountTooLowError + StakeKitErrorMessageDTO.SOLANA_UNSTAKE_AMOUNT_TOO_LOW_ERROR -> + StakingError.SolanaUnstakeAmountTooLowError + StakeKitErrorMessageDTO.SOLANA_STAKE_ACCOUNTS_NOT_FOUND_ERROR -> + StakingError.SolanaStakeAccountsNotFoundError + StakeKitErrorMessageDTO.SOLANA_ELIGIBLE_STAKE_ACCOUNTS_NOT_FOUND_ERROR -> + StakingError.SolanaEligibleStakeAccountsNotFoundError + StakeKitErrorMessageDTO.TEZOS_NO_BALANCE_DELEGATED_ERROR -> + StakingError.TezosNoBalanceDelegatedError + StakeKitErrorMessageDTO.TEZOS_MISSING_PUBKEY_ARGUMENT_ERROR -> + StakingError.TezosMissingPubkeyArgumentError + StakeKitErrorMessageDTO.TEZOS_ESTIMATE_REVEAL_GAS_LIMIT_ERROR -> + StakingError.TezosEstimateRevealGasLimitError + StakeKitErrorMessageDTO.TEZOS_BALANCE_ALREADY_DELEGATED_ERROR -> + StakingError.TezosBalanceAlreadyDelegatedError + StakeKitErrorMessageDTO.BINANCE_ACCOUNT_NOT_FOUND_ERROR -> + StakingError.BinanceAccountNotFoundError + StakeKitErrorMessageDTO.BINANCE_MISSING_ACCOUNT_NUMBER_OR_SEQUENCE_ERROR -> + StakingError.BinanceMissingAccountNumberOrSequenceError + StakeKitErrorMessageDTO.GRT_STAKING_DISABLED_ERROR -> + StakingError.GRTStakingDisabledError + StakeKitErrorMessageDTO.GRT_STAKING_DISABLED_LEDGER_LIVE_ERROR -> + StakingError.GRTStakingDisabledLedgerLiveError + else -> StakingError.UnknownError + } + } catch (e: Exception) { + StakingError.UnknownError + } + } +} \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/di/StakingDataModule.kt b/data/staking/src/main/java/com/tangem/data/staking/di/StakingDataModule.kt index 87b0102d21..f0562851c1 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/di/StakingDataModule.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/di/StakingDataModule.kt @@ -1,11 +1,17 @@ package com.tangem.data.staking.di +import com.squareup.moshi.Moshi import com.tangem.data.common.cache.CacheRegistry +import com.tangem.data.staking.DefaultStakingErrorResolver import com.tangem.data.staking.DefaultStakingRepository +import com.tangem.data.staking.converters.error.StakeKitErrorConverter import com.tangem.datasource.api.stakekit.StakeKitApi +import com.tangem.datasource.api.stakekit.models.response.model.error.StakeKitErrorResponse +import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.token.StakingBalanceStore import com.tangem.datasource.local.token.StakingYieldsStore +import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -40,4 +46,13 @@ internal object StakingDataModule { stakingFeatureToggle = stakingFeatureToggle, ) } + + @Provides + @Singleton + internal fun provideStakingErrorResolver(@NetworkMoshi moshi: Moshi): StakingErrorResolver { + val jsonAdapter = moshi.adapter(StakeKitErrorResponse::class.java) + return DefaultStakingErrorResolver( + stakeKitErrorConverter = StakeKitErrorConverter(jsonAdapter), + ) + } } \ No newline at end of file diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingError.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingError.kt new file mode 100644 index 0000000000..0f1ff03f2b --- /dev/null +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingError.kt @@ -0,0 +1,92 @@ +package com.tangem.domain.staking.model + +sealed class StakingError { + + // region stakekit errors + + data class MinimumAmountNotReachedError(val amount: String) : StakingError() + + data class MissingArgumentsError(val arguments: String) : StakingError() + + data class YieldUnderMaintenanceError(val yieldId: String) : StakingError() + + data object InsufficientFundsError : StakingError() + + data object StakedPositionNotFoundError : StakingError() + + data object InvalidAmountSubmittedError : StakingError() + + data object BalanceUnavailableError : StakingError() + + data object GasPriceUnavailableError : StakingError() + + data object NotImplementedError : StakingError() + + data object TokenNotFoundError : StakingError() + + data object BroadcastTransactionError : StakingError() + + data object MissingGasPriceStrategyError : StakingError() + + data object SubstrateMalformedTransactionHashError : StakingError() + + data object TronMaximumAmountOfValidatorsExceededError : StakingError() + + data object SubstratePoolNotFoundError : StakingError() + + data object SubstrateBondedAmountTooLowError : StakingError() + + data object TronMissingResourceTypeArgumentError : StakingError() + + data object AaveV3PoolFrozenError : StakingError() + + data object AaveV3TokenPairNotFoundError : StakingError() + + data object YearnVaultAtMaxCapacityError : StakingError() + + data object StETHNoWithdrawalRequestsFoundError : StakingError() + + data object MorphoLendingPoolPausedError : StakingError() + + data object NonceUnavailableError : StakingError() + + data object CosmosAcccountNotFoundError : StakingError() + + data object AvalancheMissingAdditionalAddressesArgumentError : StakingError() + + data object AvalancheValidatorInfoNotFoundError : StakingError() + + data object SolanaTransactionSignatureVerificationFailureError : StakingError() + + data object SolanaUnableTocreateStakeAccountError : StakingError() + + data object SolanaStakeAmountTooLowError : StakingError() + + data object SolanaUnstakeAmountTooLowError : StakingError() + + data object SolanaStakeAccountsNotFoundError : StakingError() + + data object SolanaEligibleStakeAccountsNotFoundError : StakingError() + + data object TezosNoBalanceDelegatedError : StakingError() + + data object TezosMissingPubkeyArgumentError : StakingError() + + data object TezosEstimateRevealGasLimitError : StakingError() + + data object TezosBalanceAlreadyDelegatedError : StakingError() + + data object BinanceAccountNotFoundError : StakingError() + + data object BinanceMissingAccountNumberOrSequenceError : StakingError() + + data object GRTStakingDisabledError : StakingError() + + data object GRTStakingDisabledLedgerLiveError : StakingError() + + // endregion + + data class DataError(val cause: Throwable) : StakingError() + + data object UnknownError : StakingError() +} \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingTokensUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingTokensUseCase.kt index 47e9960974..24f9b37b0e 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingTokensUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingTokensUseCase.kt @@ -3,7 +3,8 @@ package com.tangem.domain.staking import arrow.core.Either import arrow.core.raise.catch import arrow.core.raise.either -import com.tangem.domain.staking.error.StakingTokensError +import com.tangem.domain.staking.model.StakingError +import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository /** @@ -11,12 +12,13 @@ import com.tangem.domain.staking.repositories.StakingRepository */ class FetchStakingTokensUseCase( private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, ) { - suspend operator fun invoke(isRefresh: Boolean = false): Either { + suspend operator fun invoke(isRefresh: Boolean = false): Either { return either { catch( block = { stakingRepository.fetchEnabledYields(isRefresh) }, - catch = { StakingTokensError.DataError(it) }, + catch = { stakingErrorResolver.resolve(it) }, ) } } diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingYieldBalanceUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingYieldBalanceUseCase.kt index 525fd569cb..a2ff4120c1 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingYieldBalanceUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/FetchStakingYieldBalanceUseCase.kt @@ -1,23 +1,35 @@ package com.tangem.domain.staking import arrow.core.Either +import arrow.core.raise.catch +import arrow.core.raise.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.CryptoCurrencyAddress import com.tangem.domain.wallets.models.UserWalletId class FetchStakingYieldBalanceUseCase( private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, ) { suspend operator fun invoke( userWalletId: UserWalletId, address: CryptoCurrencyAddress, refresh: Boolean = false, - ): Either = Either.catch { - stakingRepository.fetchSingleYieldBalance( - userWalletId = userWalletId, - address = address, - refresh = refresh, - ) + ): Either { + return either { + catch( + block = { + stakingRepository.fetchSingleYieldBalance( + userWalletId = userWalletId, + address = address, + refresh = refresh, + ) + }, + catch = { stakingErrorResolver.resolve(it) }, + ) + } } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingAvailabilityUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingAvailabilityUseCase.kt index 2cc658f615..9000f0af29 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingAvailabilityUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingAvailabilityUseCase.kt @@ -1,6 +1,10 @@ package com.tangem.domain.staking +import arrow.core.Either +import arrow.core.raise.catch import com.tangem.domain.staking.model.StakingAvailability +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.CryptoCurrency @@ -9,9 +13,15 @@ import com.tangem.domain.tokens.model.CryptoCurrency */ class GetStakingAvailabilityUseCase( private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, ) { - suspend operator fun invoke(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): StakingAvailability { - return stakingRepository.getStakingAvailabilityForActions(cryptoCurrencyId, symbol) + suspend operator fun invoke( + cryptoCurrencyId: CryptoCurrency.ID, + symbol: String, + ): Either { + return Either + .catch { stakingRepository.getStakingAvailabilityForActions(cryptoCurrencyId, symbol) } + .mapLeft { stakingErrorResolver.resolve(it) } } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingEntryInfoUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingEntryInfoUseCase.kt index 02a505aa03..451284a714 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingEntryInfoUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingEntryInfoUseCase.kt @@ -2,14 +2,21 @@ package com.tangem.domain.staking import arrow.core.Either import com.tangem.domain.staking.model.StakingEntryInfo +import com.tangem.domain.staking.model.StakingError +import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository /** * Use case for getting entry info about staking on token screen. */ -class GetStakingEntryInfoUseCase(private val stakingRepository: StakingRepository) { +class GetStakingEntryInfoUseCase( + private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, +) { - suspend operator fun invoke(integrationId: String): Either { - return Either.catch { stakingRepository.getEntryInfo(integrationId) } + suspend operator fun invoke(integrationId: String): Either { + return Either + .catch { stakingRepository.getEntryInfo(integrationId) } + .mapLeft { stakingErrorResolver.resolve(it) } } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingYieldBalanceUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingYieldBalanceUseCase.kt index f2e7c1440a..77ac00f093 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingYieldBalanceUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/GetStakingYieldBalanceUseCase.kt @@ -4,7 +4,9 @@ import arrow.core.Either import arrow.core.left import arrow.core.right import com.tangem.domain.core.utils.EitherFlow +import com.tangem.domain.staking.model.StakingError import com.tangem.domain.staking.model.YieldBalance +import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.model.CryptoCurrencyAddress import com.tangem.domain.wallets.models.UserWalletId @@ -13,16 +15,17 @@ import kotlinx.coroutines.flow.map class GetStakingYieldBalanceUseCase( private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, ) { operator fun invoke( userWalletId: UserWalletId, address: CryptoCurrencyAddress, - ): EitherFlow { + ): EitherFlow { return stakingRepository.getSingleYieldBalanceFlow( userWalletId = userWalletId, address = address, - ).map> { it.right() } - .catch { emit(it.left()) } + ).map> { it.right() } + .catch { emit(stakingErrorResolver.resolve(it).left()) } } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/GetYieldUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/GetYieldUseCase.kt index a63dc81cdc..92d0d6e3c4 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/GetYieldUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/GetYieldUseCase.kt @@ -1,16 +1,24 @@ package com.tangem.domain.staking import arrow.core.Either +import arrow.core.raise.catch +import com.tangem.domain.staking.model.StakingError import com.tangem.domain.staking.model.Yield +import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository import com.tangem.domain.tokens.model.CryptoCurrency /** * Use case for getting staking yield for staking scenario start. */ -class GetYieldUseCase(private val stakingRepository: StakingRepository) { +class GetYieldUseCase( + private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, +) { - suspend operator fun invoke(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): Either { - return Either.catch { stakingRepository.getYield(cryptoCurrencyId, symbol) } + suspend operator fun invoke(cryptoCurrencyId: CryptoCurrency.ID, symbol: String): Either { + return Either + .catch { stakingRepository.getYield(cryptoCurrencyId, symbol) } + .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/InitializeStakingProcessUseCase.kt index a12b75f7ae..4a9fc87c47 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/InitializeStakingProcessUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/InitializeStakingProcessUseCase.kt @@ -1,9 +1,11 @@ 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.StakingTransaction +import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository import kotlinx.coroutines.delay import java.math.BigDecimal @@ -11,7 +13,10 @@ import java.math.BigDecimal /** * Use case for creating enter action */ -class InitializeStakingProcessUseCase(private val stakingRepository: StakingRepository) { +class InitializeStakingProcessUseCase( + private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, +) { suspend operator fun invoke( integrationId: String, @@ -19,7 +24,7 @@ class InitializeStakingProcessUseCase(private val stakingRepository: StakingRepo address: String, validatorAddress: String, token: Token, - ): Either> { + ): Either> { return Either.catch { val createAction = stakingRepository.createEnterAction( integrationId = integrationId, @@ -36,6 +41,8 @@ class InitializeStakingProcessUseCase(private val stakingRepository: StakingRepo val patchedTransaction = stakingRepository.constructTransaction(createdTransaction.id) createAction to patchedTransaction + }.mapLeft { + stakingErrorResolver.resolve(it) } } diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/SaveUnsubmittedHashUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/SaveUnsubmittedHashUseCase.kt index 009469c351..4e7e5efedc 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/SaveUnsubmittedHashUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/SaveUnsubmittedHashUseCase.kt @@ -1,15 +1,20 @@ package com.tangem.domain.staking import arrow.core.Either +import com.tangem.domain.staking.model.StakingError import com.tangem.domain.staking.model.UnsubmittedTransactionMetadata +import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingRepository /** * Use case for saving hash that failed to submit during staking confirmation */ -class SaveUnsubmittedHashUseCase(private val stakingRepository: StakingRepository) { +class SaveUnsubmittedHashUseCase( + private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, +) { - suspend operator fun invoke(transactionId: String, transactionHash: String): Either { + suspend operator fun invoke(transactionId: String, transactionHash: String): Either { return Either.catch { stakingRepository.storeUnsubmittedHash( unsubmittedTransactionMetadata = UnsubmittedTransactionMetadata( @@ -17,6 +22,8 @@ class SaveUnsubmittedHashUseCase(private val stakingRepository: StakingRepositor transactionHash = transactionHash, ), ) + }.mapLeft { + stakingErrorResolver.resolve(it) } } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/SendUnsubmittedHashesUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/SendUnsubmittedHashesUseCase.kt index 5c2fbd531d..6a83ee4624 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/SendUnsubmittedHashesUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/SendUnsubmittedHashesUseCase.kt @@ -1,16 +1,21 @@ 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 /** * Use case for commiting hashes that failed to submit during staking confirmation */ -class SendUnsubmittedHashesUseCase(private val stakingRepository: StakingRepository) { +class SendUnsubmittedHashesUseCase( + private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, +) { - suspend operator fun invoke(): Either { - return Either.catch { - stakingRepository.sendUnsubmittedHashes() - } + suspend operator fun invoke(): Either { + return Either + .catch { stakingRepository.sendUnsubmittedHashes() } + .mapLeft { stakingErrorResolver.resolve(it) } } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/SubmitHashUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/SubmitHashUseCase.kt index 091d9a2f6b..8fd4ce8d18 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/SubmitHashUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/SubmitHashUseCase.kt @@ -1,19 +1,27 @@ 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 /** * Use case for submitting transaction hash to stakekit */ -class SubmitHashUseCase(private val stakingRepository: StakingRepository) { +class SubmitHashUseCase( + private val stakingRepository: StakingRepository, + private val stakingErrorResolver: StakingErrorResolver, +) { - suspend fun submitHash(transactionId: String, transactionHash: String): Either { - return Either.catch { - stakingRepository.submitHash( - transactionId = transactionId, - transactionHash = transactionHash, - ) - } + suspend fun submitHash(transactionId: String, transactionHash: String): Either { + return Either + .catch { + stakingRepository.submitHash( + transactionId = transactionId, + transactionHash = transactionHash, + ) + }.mapLeft { + stakingErrorResolver.resolve(it) + } } } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/error/StakingTokensError.kt b/domain/staking/src/main/java/com/tangem/domain/staking/error/StakingTokensError.kt deleted file mode 100644 index d97a592cbd..0000000000 --- a/domain/staking/src/main/java/com/tangem/domain/staking/error/StakingTokensError.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.tangem.domain.staking.error - -sealed class StakingTokensError { - - data class DataError(val cause: Throwable) : StakingTokensError() -} \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingErrorResolver.kt b/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingErrorResolver.kt new file mode 100644 index 0000000000..c08fdb199d --- /dev/null +++ b/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingErrorResolver.kt @@ -0,0 +1,8 @@ +package com.tangem.domain.staking.repositories + +import com.tangem.domain.staking.model.* + +interface StakingErrorResolver { + + fun resolve(throwable: Throwable): StakingError +} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt index 789a0a6f82..512875fb4b 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt @@ -19,6 +19,7 @@ import com.tangem.domain.card.NetworkHasDerivationUseCase import com.tangem.domain.common.CardTypesResolver import com.tangem.domain.staking.model.StakingAvailability import com.tangem.domain.staking.model.StakingEntryInfo +import com.tangem.domain.staking.model.StakingError import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.* import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning @@ -239,7 +240,7 @@ internal class TokenDetailsStateFactory( ) } - fun getStateWithStaking(stakingEither: Either): TokenDetailsState { + fun getStateWithStaking(stakingEither: Either): TokenDetailsState { return currentStateProvider().copy( stakingBlocksState = stakingStateConverter.convert(stakingEither), ) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt index d7f0e655f9..6f3e41632f 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt @@ -3,6 +3,7 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory import arrow.core.Either import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.domain.staking.model.StakingEntryInfo +import com.tangem.domain.staking.model.StakingError import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockUM import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents @@ -12,9 +13,9 @@ import com.tangem.utils.converter.Converter internal class TokenStakingStateConverter( private val clickIntents: TokenDetailsClickIntents, private val currentStateProvider: Provider, -) : Converter, StakingBlockUM> { +) : Converter, StakingBlockUM> { - override fun convert(value: Either): StakingBlockUM { + override fun convert(value: Either): StakingBlockUM { val state = currentStateProvider() if (state.stakingBlocksState is StakingBlockUM.Staked) return state.stakingBlocksState diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt index 245dd160ad..4c32037a24 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt @@ -389,7 +389,8 @@ internal class TokenDetailsViewModel @Inject constructor( val stakingAvailability = getStakingAvailabilityUseCase( cryptoCurrencyId = cryptoCurrency.id, symbol = cryptoCurrency.symbol, - ) + ).getOrElse { StakingAvailability.Unavailable } + internalUiState.value = stateFactory.getStateWithUpdatedStakingAvailability(stakingAvailability) if (stakingAvailability is StakingAvailability.Available) { val stakingInfo = getStakingEntryInfoUseCase(stakingAvailability.integrationId)