From af7c7ed87f3f0c167b27e2dec81375a2db18f0ca Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Sep 2024 12:38:38 +0400 Subject: [PATCH 1/6] Updated on 2026-08-14 --- .../tangem/domain/managetokens/GetSupportedNetworksUseCase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/GetSupportedNetworksUseCase.kt b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/GetSupportedNetworksUseCase.kt index 1074a21b02..6a1a96966c 100644 --- a/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/GetSupportedNetworksUseCase.kt +++ b/domain/manage-tokens/src/main/kotlin/com/tangem/domain/managetokens/GetSupportedNetworksUseCase.kt @@ -21,7 +21,7 @@ class GetSupportedNetworksUseCase( ensureNotNull(networks.takeIf { it.isNotEmpty() }) { SupportedBlockchainException.EmptyList - } + }.sortedBy(Network::name) } } } \ No newline at end of file From 2b1a586572ea29e552508de88d64c624fbab10c8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Sep 2024 11:55:05 +0300 Subject: [PATCH 2/6] Updated on 2026-08-14 --- .../operations/CurrenciesStatusesOperations.kt | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesOperations.kt index bea881092e..ac688c34ef 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesOperations.kt @@ -151,13 +151,12 @@ internal class CurrenciesStatusesOperations( val currenciesFlow = combine( getQuotes(currenciesIds), getNetworksStatuses(networks), - getYieldBalances(nonEmptyCurrencies), - ) { maybeQuotes, maybeNetworksStatuses, maybeYieldBalances -> + ) { maybeQuotes, maybeNetworksStatuses -> createCurrenciesStatuses( currencies = nonEmptyCurrencies, maybeQuotes = maybeQuotes, maybeNetworkStatuses = maybeNetworksStatuses, - maybeYieldBalances = maybeYieldBalances, + maybeYieldBalances = null, ) } @@ -403,15 +402,6 @@ internal class CurrenciesStatusesOperations( .onEmpty { emit(Error.EmptyNetworksStatuses.left()) } } - private fun getYieldBalances(cryptoCurrencies: List): Flow> { - return stakingRepository.getMultiYieldBalanceFlow( - userWalletId = userWalletId, - cryptoCurrencies = cryptoCurrencies, - ).map> { it.right() } - .catch { emit(Error.DataError(it).left()) } - .onEmpty { emit(Error.EmptyYieldBalances.left()) } - } - private suspend fun getYieldBalancesSync( cryptoCurrencies: List, ): Either { From 8251b2ec981dca2633aef33990ec9ad6670ac122 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Sep 2024 14:58:07 +0500 Subject: [PATCH 3/6] Updated on 2026-08-14 --- .../state/transformers/AddStakingNotificationsTransformer.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt index 181d37a8a2..bd7988cd8f 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt @@ -81,11 +81,11 @@ internal class AddStakingNotificationsTransformer( amountValue = amountValue, feeValue = feeValue, reduceAmountBy = reduceAmountBy, - ) + ).max(minimumRequirement) } else { // No amount is taken from account balance on exit or pending actions BigDecimal.ZERO - }.max(minimumRequirement) + } val notifications = buildList { // errors From 4c525f0cada9f662424cfd9c6090e03cdca34fbf Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Sep 2024 14:58:20 +0500 Subject: [PATCH 4/6] Updated on 2026-08-14 --- .../impl/presentation/state/utils/StakingPendingActionUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/StakingPendingActionUtils.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/StakingPendingActionUtils.kt index 2822f01758..efda617b73 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/StakingPendingActionUtils.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/StakingPendingActionUtils.kt @@ -32,5 +32,5 @@ internal fun StakingActionType?.getPendingActionTitle(): TextReference = when (t internal fun isSolanaWithdraw(networkId: String, pendingActions: ImmutableList?): Boolean { val isSolana = isSolana(networkId) val isWithdraw = pendingActions?.all { it.type == StakingActionType.WITHDRAW } == true - return isSolana && isWithdraw + return isSolana && isWithdraw && !pendingActions.isNullOrEmpty() } \ No newline at end of file From 3645815d0a90550cdf7eccdbcae253f6fb1ad017 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Sep 2024 14:58:45 +0500 Subject: [PATCH 5/6] Updated on 2026-08-14 --- .../stakekit/action/StakingActionType.kt | 34 +++++++++---------- .../impl/analytics/StakingAnalyticsEvents.kt | 10 ++++-- .../analytics/utils/StakingAnalyticSender.kt | 1 + .../helpers/StakingFeeTransactionLoader.kt | 15 ++++---- .../state/helpers/StakingTransactionSender.kt | 14 ++++++-- .../viewmodel/StakingViewModel.kt | 26 +++++++++++--- 6 files changed, 67 insertions(+), 33 deletions(-) diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionType.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionType.kt index 5098ec0ce1..9f8cbf56e0 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionType.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionType.kt @@ -1,20 +1,20 @@ package com.tangem.domain.staking.model.stakekit.action -enum class StakingActionType { - STAKE, - UNSTAKE, - CLAIM_REWARDS, - RESTAKE_REWARDS, - WITHDRAW, - RESTAKE, - CLAIM_UNSTAKED, - UNLOCK_LOCKED, - STAKE_LOCKED, - VOTE, - REVOKE, - VOTE_LOCKED, - REVOTE, - REBOND, - MIGRATE, - UNKNOWN, +enum class StakingActionType(val type: String) { + STAKE("Stake"), + UNSTAKE("Unstake"), + CLAIM_REWARDS("Claim Rewards"), + RESTAKE_REWARDS("Restake Rewards"), + WITHDRAW("Withdraw"), + RESTAKE("Restake"), + CLAIM_UNSTAKED("Claim Unstaked"), + UNLOCK_LOCKED("Unlock Locked"), + STAKE_LOCKED("Stake Locked"), + VOTE("Vote"), + REVOKE("Revoke"), + VOTE_LOCKED("Vote Locked"), + REVOTE("Revote"), + REBOND("Rebond"), + MIGRATE("Migrate"), + UNKNOWN("Unknown"), } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt index 336486156f..27d67bf6aa 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt @@ -47,18 +47,20 @@ internal sealed class StakingAnalyticsEvents( params = mapOf( AnalyticsParam.TOKEN_PARAM to token, "Validator" to validator, - "Action" to action.name, + "Action" to action.type, ), ) data class StakeInProgressScreenOpened( val validator: String, val token: String, + val action: StakingActionType, ) : StakingAnalyticsEvents( event = "Stake In Progress Screen Opened", params = mapOf( AnalyticsParam.TOKEN_PARAM to token, "Validator" to validator, + "Action" to action.type, ), ) @@ -136,9 +138,13 @@ internal sealed class StakingAnalyticsEvents( data class StakingError( val token: String, + val errorType: String, ) : StakingAnalyticsEvents( event = "Errors", - params = mapOf(AnalyticsParam.TOKEN_PARAM to token), + params = mapOf( + AnalyticsParam.TOKEN_PARAM to token, + "ErrorType" to errorType, + ), ) data class TransactionError( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt index 013bf2e49f..be35fd0eaa 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt @@ -104,6 +104,7 @@ internal class StakingAnalyticSender( StakingAnalyticsEvents.StakeInProgressScreenOpened( validator = validatorName, token = value.cryptoCurrencySymbol, + action = getStakingActionType(value), ), ) } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt index 0fdda4ab88..4eb21da85c 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt @@ -49,9 +49,10 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( suspend fun getFee( pendingAction: PendingAction?, pendingActions: ImmutableList?, - onFeeError: (GetFeeError) -> Unit, onStakingFee: (Fee) -> Unit, + onStakingFeeError: (StakingError) -> Unit, onApprovalFee: (TransactionFee) -> Unit, + onFeeError: (GetFeeError) -> Unit, ) { val state = stateController.value val confirmationState = state.confirmationState as? StakingStates.ConfirmationState.Data @@ -85,7 +86,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( pendingActions = pendingActions, amount = amount, validatorAddress = validatorAddress, - onFeeError = onFeeError, + onStakingFeeError = onStakingFeeError, onStakingFee = onStakingFee, ) } @@ -95,7 +96,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( pendingActions = pendingActions, amount = amount, validatorAddress = validatorAddress, - onFeeError = onFeeError, + onStakingFeeError = onStakingFeeError, onStakingFee = onStakingFee, ) } @@ -106,7 +107,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( pendingActions: ImmutableList?, amount: BigDecimal, validatorAddress: String, - onFeeError: (GetFeeError) -> Unit, + onStakingFeeError: (StakingError) -> Unit, onStakingFee: (Fee) -> Unit, ) { val sourceAddress = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value @@ -125,7 +126,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( action = action, ) }.getOrElse { - onFeeError(GetFeeError.DataError(Throwable(it.toString()))) + onStakingFeeError(it) null } } @@ -133,7 +134,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( } if (result.isNullOrEmpty()) { - onFeeError(GetFeeError.UnknownError) + onStakingFeeError(StakingError.UnknownError) return } @@ -151,7 +152,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( validatorAddress = validatorAddress, action = pendingAction, ).getOrElse { - onFeeError(GetFeeError.DataError(Throwable(it.toString()))) + onStakingFeeError(it) return } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt index 109dafb912..35b8a1ec9b 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt @@ -185,7 +185,12 @@ internal class StakingTransactionSender @AssistedInject constructor( type = action?.type, ), ).getOrElse { - analyticsEventHandler.send(StakingAnalyticsEvents.StakingError(state.cryptoCurrencyName)) + analyticsEventHandler.send( + StakingAnalyticsEvents.StakingError( + token = state.cryptoCurrencyName, + errorType = it.javaClass.simpleName, + ), + ) onConstructError(it) return emptyList() } @@ -248,9 +253,12 @@ internal class StakingTransactionSender @AssistedInject constructor( rawCurrencyId = rawCurrencyId, ), ) - .onLeft { + .onLeft { error -> analyticsEventHandler.send( - StakingAnalyticsEvents.StakingError(stateController.value.cryptoCurrencyName), + StakingAnalyticsEvents.StakingError( + token = stateController.value.cryptoCurrencyName, + errorType = error.javaClass.simpleName, + ), ) saveUnsubmittedHashUseCase.invoke( transactionId = transactionId, 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 913bf9b07a..a5afd54f97 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 @@ -1,7 +1,10 @@ package com.tangem.features.staking.impl.presentation.viewmodel import android.os.Bundle -import androidx.lifecycle.* +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import arrow.core.getOrElse import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.common.routing.AppRoute @@ -256,8 +259,18 @@ internal class StakingViewModel @Inject constructor( ) updateNotifications() }, + onStakingFeeError = { error -> + analyticsEventHandler.send( + StakingAnalyticsEvents.StakingError( + value.cryptoCurrencyName, + error.javaClass.simpleName, + ), + ) + stateController.update(AddStakingErrorTransformer()) + updateNotifications(GetFeeError.UnknownError) + }, onFeeError = { error -> - analyticsEventHandler.send(StakingAnalyticsEvents.StakingError(value.cryptoCurrencyName)) + analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencyName)) stateController.update(AddStakingErrorTransformer()) updateNotifications(error) }, @@ -285,7 +298,12 @@ internal class StakingViewModel @Inject constructor( }, onConstructError = { error -> Timber.e(error.toString()) - analyticsEventHandler.send(StakingAnalyticsEvents.StakingError(value.cryptoCurrencyName)) + analyticsEventHandler.send( + StakingAnalyticsEvents.StakingError( + token = value.cryptoCurrencyName, + errorType = error.javaClass.simpleName, + ), + ) stakingEventFactory.createStakingErrorAlert(error) stateController.update(SetConfirmationStateResetAssentTransformer) }, @@ -296,7 +314,7 @@ internal class StakingViewModel @Inject constructor( }, onSendError = { error -> Timber.e(error.toString()) - analyticsEventHandler.send(StakingAnalyticsEvents.StakingError(value.cryptoCurrencyName)) + analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencyName)) stakingEventFactory.createSendTransactionErrorAlert(error) stateController.update(SetConfirmationStateResetAssentTransformer) }, From 8dd5c59f06d5b2277ab46e6f53f64973f0f97c36 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Sep 2024 13:08:02 +0300 Subject: [PATCH 6/6] Updated on 2026-08-14 --- .../state/helpers/StakingTransactionSender.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt index 109dafb912..de47658cdb 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt @@ -15,6 +15,7 @@ import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType import com.tangem.domain.staking.model.stakekit.transaction.ActionParams import com.tangem.domain.staking.model.stakekit.transaction.StakingTransaction +import com.tangem.domain.staking.model.stakekit.transaction.StakingTransactionStatus import com.tangem.domain.staking.model.stakekit.transaction.StakingTransactionType import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.transaction.error.SendTransactionError @@ -130,7 +131,10 @@ internal class StakingTransactionSender @AssistedInject constructor( fee: Fee, onConstructError: (StakingError) -> Unit, ) = coroutineScope { - stakingTransactions?.filterNot { it.type == StakingTransactionType.APPROVAL } + stakingTransactions + ?.filterNot { + it.type == StakingTransactionType.APPROVAL || it.status == StakingTransactionStatus.SKIPPED + } ?.map { transaction -> async { getConstructedStakingTransactionUseCase( @@ -150,7 +154,9 @@ internal class StakingTransactionSender @AssistedInject constructor( }, ) } - }?.awaitAll()?.filterNotNull() + } + ?.awaitAll() + ?.filterNotNull() } private suspend fun getStakingTransaction(