diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt index 9600cda393..b646142403 100644 --- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt @@ -179,6 +179,7 @@ sealed class AnalyticsParam { const val ERROR_CODE = "Error Code" const val ERROR_KEY = "Error Key" const val ERROR_TYPE = "Error Type" + const val ERROR_MESSAGE = "Error Message" const val CREATION_TYPE = "Creation type" const val DAPP_NAME = "DApp Name" const val DAPP_URL = "DApp Url" diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/di/AnalyticsModule.kt b/core/analytics/src/main/java/com/tangem/core/analytics/di/AnalyticsModule.kt index 13715236c5..18a95d3a02 100644 --- a/core/analytics/src/main/java/com/tangem/core/analytics/di/AnalyticsModule.kt +++ b/core/analytics/src/main/java/com/tangem/core/analytics/di/AnalyticsModule.kt @@ -2,6 +2,7 @@ package com.tangem.core.analytics.di import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.analytics.api.ParamsInterceptorHolder import com.tangem.core.analytics.filter.OneTimeEventFilter import com.tangem.domain.analytics.repository.AnalyticsRepository import dagger.Module @@ -20,6 +21,12 @@ internal object AnalyticsModule { return Analytics // todo replace after refactoring calling Analytics in whole project } + @Singleton + @Provides + fun provideParamsInterceptorHolder(): ParamsInterceptorHolder { + return Analytics // todo replace after refactoring calling Analytics in whole project + } + @Provides fun provideOneTimeEventFilter(analyticsRepository: AnalyticsRepository): OneTimeEventFilter { return OneTimeEventFilter(analyticsRepository) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/adapter/UnknownEnumMoshiAdapter.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/adapter/UnknownEnumMoshiAdapter.kt index 2cc525ffd0..97372a83b2 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/adapter/UnknownEnumMoshiAdapter.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/adapter/UnknownEnumMoshiAdapter.kt @@ -11,8 +11,6 @@ import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO.RewardT import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO.ValidatorDTO.ValidatorStatusDTO import com.tangem.datasource.api.stakekit.models.response.model.action.StakingActionStatusDTO import com.tangem.datasource.api.stakekit.models.response.model.action.StakingActionTypeDTO -import com.tangem.datasource.api.stakekit.models.response.model.error.AccessDeniedErrorTypeDTO -import com.tangem.datasource.api.stakekit.models.response.model.error.StakeKitErrorMessageDTO import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingTransactionStatusDTO import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingTransactionTypeDTO @@ -40,9 +38,6 @@ fun Moshi.Builder.addStakeKitEnumFallbackAdapters(): Moshi.Builder { StakingTransactionStatusDTO::class.java to StakingTransactionStatusDTO.UNKNOWN, StakingTransactionTypeDTO::class.java to StakingTransactionTypeDTO.UNKNOWN, ValidatorStatusDTO::class.java to ValidatorStatusDTO.UNKNOWN, - // error enums - AccessDeniedErrorTypeDTO::class.java to AccessDeniedErrorTypeDTO.UNKNOWN, - StakeKitErrorMessageDTO::class.java to StakeKitErrorMessageDTO.UNKNOWN, ) return apply { 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 index fdb3436051..086837d4b1 100644 --- 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 @@ -3,18 +3,21 @@ package com.tangem.datasource.api.stakekit.models.response.model.error import com.squareup.moshi.Json class StakeKitErrorResponse( + @Json(name = "message") + val message: String? = null, + @Json(name = "code") + val code: Int? = null, + @Json(name = "path") + val path: String? = null, + @Json(name = "details") val details: StakeKitErrorDetailsDTO? = null, - @Json(name = "message") - val message: StakeKitErrorMessageDTO? = null, @Json(name = "level") val level: String? = null, // unused // 403 @Json(name = "type") - val type: AccessDeniedErrorTypeDTO? = null, - @Json(name = "code") - val code: String? = null, + val type: String? = null, @Json(name = "countryCode") val countryCode: String?, @Json(name = "regionCode") @@ -30,135 +33,4 @@ data class StakeKitErrorDetailsDTO( val amount: String? = null, @Json(name = "yieldId") val yieldId: String? = null, -) - -enum class AccessDeniedErrorTypeDTO { - @Json(name = "GEO_LOCATION") - GEO_LOCATION, - - UNKNOWN, -} - -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, - - UNKNOWN, -} \ No newline at end of file +) \ 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 index 8568980711..34ebad7aa5 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingErrorResolver.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingErrorResolver.kt @@ -1,19 +1,36 @@ package com.tangem.data.staking +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.data.staking.converters.error.StakeKitErrorConverter import com.tangem.datasource.api.common.response.ApiResponseError +import com.tangem.domain.staking.analytics.StakingAnalyticsEvent import com.tangem.domain.staking.model.stakekit.StakingError import com.tangem.domain.staking.repositories.StakingErrorResolver internal class DefaultStakingErrorResolver( + private val analyticsEventHandler: AnalyticsEventHandler, private val stakeKitErrorConverter: StakeKitErrorConverter, ) : StakingErrorResolver { override fun resolve(throwable: Throwable): StakingError { - return if (throwable is ApiResponseError.HttpException) { + val error = if (throwable is ApiResponseError.HttpException) { stakeKitErrorConverter.convert(throwable.errorBody.orEmpty()) } else { - StakingError.UnknownError() + StakingError.DomainError(throwable.message) } + + when (error) { + is StakingError.StakeKitApiError -> { + analyticsEventHandler.send(StakingAnalyticsEvent.StakeKitApiError(error)) + } + is StakingError.StakeKitUnknownError -> { + analyticsEventHandler.send(StakingAnalyticsEvent.StakeKitApiUnknownError(error)) + } + else -> { + // intentionally do nothing + } + } + + return error } } \ 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 index 8b303f9292..fdc9226b7d 100644 --- 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 @@ -1,8 +1,6 @@ package com.tangem.data.staking.converters.error import com.squareup.moshi.JsonAdapter -import com.tangem.datasource.api.stakekit.models.response.model.error.AccessDeniedErrorTypeDTO -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.stakekit.StakingError import com.tangem.utils.converter.Converter @@ -11,105 +9,18 @@ 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(value) + val stakeKitErrorResponse = jsonAdapter.fromJson(value) + ?: return StakingError.StakeKitUnknownError(value) - if (stakeKitErrorResponse.type == AccessDeniedErrorTypeDTO.GEO_LOCATION) { - StakingError.UnavailableDueToGeolocationError( - tags = stakeKitErrorResponse.tags ?: emptyList(), - ) - } - - 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(value) - } + return StakingError.StakeKitApiError( + message = stakeKitErrorResponse.message, + code = stakeKitErrorResponse.code, + methodName = stakeKitErrorResponse.path, + ) } catch (e: Exception) { - StakingError.UnknownError(value) + StakingError.StakeKitUnknownError(value) } } } \ 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 e440b5c172..b9b9bd58d0 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,6 +1,7 @@ package com.tangem.data.staking.di import com.squareup.moshi.Moshi +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.data.common.cache.CacheRegistry import com.tangem.data.staking.DefaultStakingErrorResolver import com.tangem.data.staking.DefaultStakingPendingTransactionRepository @@ -79,10 +80,14 @@ internal object StakingDataModule { @Provides @Singleton - internal fun provideStakingErrorResolver(@NetworkMoshi moshi: Moshi): StakingErrorResolver { + internal fun provideStakingErrorResolver( + @NetworkMoshi moshi: Moshi, + analyticsEventHandler: AnalyticsEventHandler, + ): StakingErrorResolver { val jsonAdapter = moshi.adapter(StakeKitErrorResponse::class.java) return DefaultStakingErrorResolver( stakeKitErrorConverter = StakeKitErrorConverter(jsonAdapter), + analyticsEventHandler = analyticsEventHandler, ) } } \ No newline at end of file diff --git a/domain/staking/build.gradle.kts b/domain/staking/build.gradle.kts index 5107e30cf7..9832ec7010 100644 --- a/domain/staking/build.gradle.kts +++ b/domain/staking/build.gradle.kts @@ -12,6 +12,7 @@ android { dependencies { api(projects.domain.staking.models) api(projects.domain.core) + api(projects.core.analytics) implementation(deps.kotlin.serialization) implementation(deps.jodatime) diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/StakingError.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/StakingError.kt index b02b33741f..0d0ca16611 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/StakingError.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/StakingError.kt @@ -4,93 +4,17 @@ sealed class StakingError { // region stakekit errors - data class MinimumAmountNotReachedError(val amount: String) : StakingError() + data class StakeKitApiError( + val message: String?, + val code: Int?, + val methodName: 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() - - data class UnavailableDueToGeolocationError( - val tags: List, + data class StakeKitUnknownError( + val jsonString: String? = null, ) : StakingError() // endregion - data class DataError(val cause: Throwable) : StakingError() - - data class UnknownError(val message: String? = null) : StakingError() + data class DomainError(val message: String?) : StakingError() } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt b/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt similarity index 50% rename from features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt rename to domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt index cc612804f3..dbe640d0b0 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt @@ -1,11 +1,12 @@ -package com.tangem.features.staking.impl.analytics +package com.tangem.domain.staking.analytics import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.domain.staking.analytics.StakingAnalyticsEvent.ButtonRewards.addIfValueIsNotNull import com.tangem.domain.staking.model.stakekit.StakingError import com.tangem.domain.staking.model.stakekit.action.StakingActionType -internal sealed class StakingAnalyticsEvents( +sealed class StakingAnalyticsEvent( event: String, params: Map = mapOf(), ) : AnalyticsEvent( @@ -16,37 +17,27 @@ internal sealed class StakingAnalyticsEvents( data class StakingInfoScreenOpened( val validatorsCount: Int, - val token: String, - ) : StakingAnalyticsEvents( + ) : StakingAnalyticsEvent( event = "Staking Info Screen Opened", params = mapOf( "Validators Count" to validatorsCount.toString(), - AnalyticsParam.TOKEN_PARAM to token, ), ) - data class WhatIsStaking(val token: String) : StakingAnalyticsEvents( + data object WhatIsStaking : StakingAnalyticsEvent( event = "Link - What Is Staking", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), ) - data class AmountScreenOpened(val token: String) : StakingAnalyticsEvents( + data object AmountScreenOpened : StakingAnalyticsEvent( event = "Amount Screen Opened", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), ) data class ConfirmationScreenOpened( - val token: String, val validator: String, val action: StakingActionType, - ) : StakingAnalyticsEvents( + ) : StakingAnalyticsEvent( event = "Confirmation Screen Opened", params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, "Validator" to validator, "Action" to action.asAnalyticName, ), @@ -54,126 +45,108 @@ internal sealed class StakingAnalyticsEvents( data class StakeInProgressScreenOpened( val validator: String, - val token: String, val action: StakingActionType, - ) : StakingAnalyticsEvents( + ) : StakingAnalyticsEvent( event = "Stake In Progress Screen Opened", params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, "Validator" to validator, "Action" to action.asAnalyticName, ), ) - data class RewardScreenOpened(val token: String) : StakingAnalyticsEvents( + data object RewardScreenOpened : StakingAnalyticsEvent( event = "Reward Screen Opened", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), ) data class AmountSelectCurrency( - val token: String, val isAppCurrency: Boolean, - ) : StakingAnalyticsEvents( + ) : StakingAnalyticsEvent( event = "Selected Currency", params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, AnalyticsParam.TYPE to if (isAppCurrency) "App Currency" else "Token", ), ) - data class ButtonMax(val token: String) : StakingAnalyticsEvents( + data object ButtonMax : StakingAnalyticsEvent( event = "Button - Max", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), ) data class ButtonCancel( val source: StakeScreenSource, - val token: String, - ) : StakingAnalyticsEvents( + ) : StakingAnalyticsEvent( event = "Button - Cancel", params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, AnalyticsParam.SOURCE to source.name, ), ) data class ValidatorChosen( - val token: String, val validator: String, - ) : StakingAnalyticsEvents( + ) : StakingAnalyticsEvent( event = "Validator Chosen", params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, "Validator" to validator, ), ) data class ButtonValidator( val source: StakeScreenSource, - val token: String, - ) : StakingAnalyticsEvents( + ) : StakingAnalyticsEvent( event = "Button - Validator", params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, AnalyticsParam.SOURCE to source.name, ), ) - data class ButtonRewards( - val token: String, - ) : StakingAnalyticsEvents( + data object ButtonRewards : StakingAnalyticsEvent( event = "Button - Rewards", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), ) data class ButtonAction( val action: StakingActionType, - val token: String, val validator: String, - ) : StakingAnalyticsEvents( + ) : StakingAnalyticsEvent( event = "Button - ${action.asAnalyticName}", params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, "Validator" to validator, ), ) - data object ButtonShare : StakingAnalyticsEvents(event = "Button - Share") + data object ButtonShare : StakingAnalyticsEvent(event = "Button - Share") - data object ButtonExplore : StakingAnalyticsEvents(event = "Button - Explore") + data object ButtonExplore : StakingAnalyticsEvent(event = "Button - Explore") - data class StakekitError( - val token: String, - val stakeKitError: StakingError, - ) : StakingAnalyticsEvents( + data class StakeKitApiError( + val stakingError: StakingError.StakeKitApiError, + ) : StakingAnalyticsEvent( event = "Errors", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - AnalyticsParam.ERROR_TYPE to if (stakeKitError is StakingError.UnknownError) { - stakeKitError.message ?: "Unknown" - } else { - stakeKitError.javaClass.simpleName - }, - ), + params = buildMap { + addIfValueIsNotNull(AnalyticsParam.ERROR_MESSAGE, stakingError.message) + addIfValueIsNotNull(AnalyticsParam.ERROR_CODE, stakingError.code) + addIfValueIsNotNull(AnalyticsParam.METHOD_NAME, stakingError.methodName) + }, ) - data class TransactionError( - val token: String, - ) : StakingAnalyticsEvents( + data class StakeKitApiUnknownError( + val stakeKitUnknownError: StakingError.StakeKitUnknownError, + ) : StakingAnalyticsEvent( + event = "Errors", + params = buildMap { + addIfValueIsNotNull(AnalyticsParam.ERROR_DESCRIPTION, stakeKitUnknownError.jsonString) + }, + ) + + fun MutableMap.addIfValueIsNotNull(key: String, value: Any?) { + if (value != null) { + put(key, value.toString()) + } + } + + data object TransactionError : StakingAnalyticsEvent( event = "Error - Transaction Rejected", - params = mapOf(AnalyticsParam.TOKEN_PARAM to token), ) } enum class StakeScreenSource { - Info, - Amount, - Confirmation, - Validators, + Info, Amount, Confirmation, Validators, } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingParamsInterceptor.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingParamsInterceptor.kt new file mode 100644 index 0000000000..a11ff1ac92 --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingParamsInterceptor.kt @@ -0,0 +1,23 @@ +package com.tangem.features.staking.impl.analytics + +import com.tangem.core.analytics.api.ParamsInterceptor +import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.domain.staking.analytics.StakingAnalyticsEvent + +class StakingParamsInterceptor(private val tokenSymbol: String) : ParamsInterceptor { + + override fun id() = ID + + override fun canBeAppliedTo(event: AnalyticsEvent): Boolean { + return event is StakingAnalyticsEvent + } + + override fun intercept(params: MutableMap) { + params[AnalyticsParam.TOKEN_PARAM] = tokenSymbol + } + + companion object { + const val ID = "StakingParamsInterceptorId" + } +} \ No newline at end of file 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 0b3f4fcd35..c2ddc2a16f 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 @@ -7,8 +7,8 @@ import com.tangem.core.analytics.models.Basic import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType import com.tangem.domain.staking.model.stakekit.action.StakingActionType import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.features.staking.impl.analytics.StakeScreenSource -import com.tangem.features.staking.impl.analytics.StakingAnalyticsEvents +import com.tangem.domain.staking.analytics.StakeScreenSource +import com.tangem.domain.staking.analytics.StakingAnalyticsEvent import com.tangem.features.staking.impl.presentation.state.* internal class StakingAnalyticSender( @@ -24,9 +24,8 @@ internal class StakingAnalyticSender( ?.size ?: 0 analyticsEventHandler.send( - StakingAnalyticsEvents.StakingInfoScreenOpened( + StakingAnalyticsEvent.StakingInfoScreenOpened( validatorsCount = validatorCount, - token = value.cryptoCurrencySymbol, ), ) } @@ -39,8 +38,7 @@ internal class StakingAnalyticSender( if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) return analyticsEventHandler.send( - StakingAnalyticsEvents.ConfirmationScreenOpened( - token = value.cryptoCurrencySymbol, + StakingAnalyticsEvent.ConfirmationScreenOpened( validator = validatorName, action = getStakingActionType(value), ), @@ -49,7 +47,7 @@ internal class StakingAnalyticSender( fun screenCancel(value: StakingUiState) { analyticsEventHandler.send( - StakingAnalyticsEvents.ButtonCancel( + StakingAnalyticsEvent.ButtonCancel( source = when (value.currentStep) { StakingStep.InitialInfo -> StakeScreenSource.Info StakingStep.Amount -> StakeScreenSource.Amount @@ -58,7 +56,6 @@ internal class StakingAnalyticSender( StakingStep.RewardsValidators, -> StakeScreenSource.Validators }, - token = value.cryptoCurrencyName, ), ) } @@ -93,9 +90,8 @@ internal class StakingAnalyticSender( ), ) analyticsEventHandler.send( - StakingAnalyticsEvents.StakeInProgressScreenOpened( + StakingAnalyticsEvent.StakeInProgressScreenOpened( validator = validatorName, - token = value.cryptoCurrencySymbol, action = getStakingActionType(value), ), ) @@ -107,9 +103,8 @@ internal class StakingAnalyticSender( val validatorName = validatorState?.chosenValidator?.name ?: return analyticsEventHandler.send( - StakingAnalyticsEvents.ButtonAction( + StakingAnalyticsEvent.ButtonAction( action = getStakingActionType(value), - token = value.cryptoCurrencySymbol, validator = validatorName, ), ) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt index 69cca72194..64167ead85 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt @@ -3,7 +3,7 @@ package com.tangem.features.staking.impl.presentation.state import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType -import com.tangem.features.staking.impl.analytics.StakingAnalyticsEvents +import com.tangem.domain.staking.analytics.StakingAnalyticsEvent import com.tangem.features.staking.impl.analytics.utils.StakingAnalyticSender internal class StakingStateRouter( @@ -60,16 +60,12 @@ internal class StakingStateRouter( } private fun showRewardsValidators() { - analyticsEventsHandler.send( - StakingAnalyticsEvents.RewardScreenOpened(stateController.value.cryptoCurrencySymbol), - ) + analyticsEventsHandler.send(StakingAnalyticsEvent.RewardScreenOpened) stateController.update { it.copy(currentStep = StakingStep.RewardsValidators) } } private fun showAmount() { - analyticsEventsHandler.send( - StakingAnalyticsEvents.AmountScreenOpened(stateController.value.cryptoCurrencySymbol), - ) + analyticsEventsHandler.send(StakingAnalyticsEvent.AmountScreenOpened) stateController.update { it.copy(currentStep = StakingStep.Amount) } } 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 cfc9a504be..a49da3f88d 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 @@ -135,7 +135,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( } if (result.isNullOrEmpty()) { - onStakingFeeError(StakingError.UnknownError()) + onStakingFeeError(StakingError.DomainError("Error estimating fee")) 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 f330139497..addda5d313 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 @@ -4,7 +4,6 @@ import arrow.core.getOrElse import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.transaction.Fee import com.tangem.common.ui.amountScreen.models.AmountState -import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.staking.* import com.tangem.domain.staking.model.PendingTransaction import com.tangem.domain.staking.model.SubmitHashData @@ -20,7 +19,6 @@ import com.tangem.domain.transaction.usecase.SendTransactionUseCase import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase import com.tangem.domain.utils.convertToSdkAmount import com.tangem.domain.wallets.models.UserWallet -import com.tangem.features.staking.impl.analytics.StakingAnalyticsEvents import com.tangem.features.staking.impl.presentation.state.* import com.tangem.features.staking.impl.presentation.state.utils.checkAndCalculateSubtractedAmount import com.tangem.features.staking.impl.presentation.state.utils.isSolanaWithdraw @@ -46,7 +44,6 @@ internal class StakingTransactionSender @AssistedInject constructor( private val submitHashUseCase: SubmitHashUseCase, private val saveUnsubmittedHashUseCase: SaveUnsubmittedHashUseCase, private val savePendingTransactionUseCase: SavePendingTransactionUseCase, - private val analyticsEventHandler: AnalyticsEventHandler, @Assisted private val cryptoCurrencyStatus: CryptoCurrencyStatus, @Assisted private val userWallet: UserWallet, @Assisted private val yield: Yield, @@ -84,7 +81,7 @@ internal class StakingTransactionSender @AssistedInject constructor( ) if (fullTransactionsData.isNullOrEmpty()) { - onConstructError(StakingError.UnknownError()) + onConstructError(StakingError.DomainError("fullTransactionsData is null or empty")) return } @@ -198,12 +195,6 @@ internal class StakingTransactionSender @AssistedInject constructor( type = action?.type, ), ).getOrElse { - analyticsEventHandler.send( - StakingAnalyticsEvents.StakekitError( - token = state.cryptoCurrencySymbol, - stakeKitError = it, - ), - ) onConstructError(it) return emptyList() } @@ -255,13 +246,7 @@ internal class StakingTransactionSender @AssistedInject constructor( pendingTransaction = pendingTransaction, ), ) - .onLeft { error -> - analyticsEventHandler.send( - StakingAnalyticsEvents.StakekitError( - token = stateController.value.cryptoCurrencySymbol, - stakeKitError = error, - ), - ) + .onLeft { saveUnsubmittedHashUseCase.invoke( transactionId = transaction.id, transactionHash = transactionHash, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingErrorTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingErrorTransformer.kt index 5acae90ea3..85f0bf2323 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingErrorTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingErrorTransformer.kt @@ -32,14 +32,8 @@ internal class AddStakingErrorTransformer( } private fun convertToNotification(error: StakingError): NotificationUM { - return when (error) { - is StakingError.StakedPositionNotFoundError -> StakingNotification.Error.StakedPositionNotFoundError( - message = error.toString(), - ) - // TODO staking - else -> StakingNotification.Error.Common( - subtitle = stringReference(error.toString()), - ) - } + return StakingNotification.Error.Common( + subtitle = stringReference(error.toString()), + ) } } \ No newline at end of file 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 93a483ce0a..40cc866b89 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 @@ -15,6 +15,7 @@ import com.tangem.common.ui.bottomsheet.permission.state.ApproveType import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionBottomSheetConfig import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.analytics.api.ParamsInterceptorHolder import com.tangem.core.ui.haptic.TangemHapticEffect import com.tangem.core.ui.haptic.VibratorHapticManager import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase @@ -47,8 +48,9 @@ import com.tangem.domain.utils.convertToSdkAmount import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase -import com.tangem.features.staking.impl.analytics.StakeScreenSource -import com.tangem.features.staking.impl.analytics.StakingAnalyticsEvents +import com.tangem.domain.staking.analytics.StakeScreenSource +import com.tangem.domain.staking.analytics.StakingAnalyticsEvent +import com.tangem.features.staking.impl.analytics.StakingParamsInterceptor import com.tangem.features.staking.impl.analytics.utils.StakingAnalyticSender import com.tangem.features.staking.impl.navigation.InnerStakingRouter import com.tangem.features.staking.impl.presentation.state.* @@ -106,6 +108,7 @@ internal class StakingViewModel @Inject constructor( private val stakingBalanceUpdater: StakingBalanceUpdater.Factory, private val analyticsEventHandler: AnalyticsEventHandler, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, + private val paramsInterceptorHolder: ParamsInterceptorHolder, @DelayedWork private val coroutineScope: CoroutineScope, savedStateHandle: SavedStateHandle, ) : ViewModel(), DefaultLifecycleObserver, StakingClickIntents { @@ -201,6 +204,7 @@ internal class StakingViewModel @Inject constructor( override fun onCleared() { super.onCleared() + paramsInterceptorHolder.removeParamsInterceptor(StakingParamsInterceptor.ID) approvalJobHolder.cancel() feeJobHolder.cancel() sendTransactionJobHolder.cancel() @@ -297,18 +301,12 @@ internal class StakingViewModel @Inject constructor( ) updateNotifications() }, - onStakingFeeError = { error -> - analyticsEventHandler.send( - StakingAnalyticsEvents.StakekitError( - value.cryptoCurrencySymbol, - error, - ), - ) + onStakingFeeError = { stateController.update(AddStakingErrorTransformer()) updateNotifications(GetFeeError.UnknownError) }, onFeeError = { error -> - analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencySymbol)) + analyticsEventHandler.send(StakingAnalyticsEvent.TransactionError) stateController.update(AddStakingErrorTransformer()) updateNotifications(error) }, @@ -336,13 +334,6 @@ internal class StakingViewModel @Inject constructor( transactionsInProgress.addAll(constructedTransactions) }, onConstructError = { error -> - Timber.e(error.toString()) - analyticsEventHandler.send( - StakingAnalyticsEvents.StakekitError( - token = value.cryptoCurrencySymbol, - stakeKitError = error, - ), - ) stakingEventFactory.createStakingErrorAlert(error) stateController.update(SetConfirmationStateResetAssentTransformer) }, @@ -353,7 +344,7 @@ internal class StakingViewModel @Inject constructor( }, onSendError = { error -> Timber.e(error.toString()) - analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencySymbol)) + analyticsEventHandler.send(StakingAnalyticsEvent.TransactionError) stakingEventFactory.createSendTransactionErrorAlert(error) stateController.update(SetConfirmationStateResetAssentTransformer) }, @@ -399,7 +390,7 @@ internal class StakingViewModel @Inject constructor( } override fun onInitialInfoBannerClick() { - analyticsEventHandler.send(StakingAnalyticsEvents.WhatIsStaking(value.cryptoCurrencySymbol)) + analyticsEventHandler.send(StakingAnalyticsEvent.WhatIsStaking) innerRouter.openUrl(WHAT_IS_STAKING_ARTICLE_URL) } @@ -446,22 +437,21 @@ internal class StakingViewModel @Inject constructor( } override fun onMaxValueClick() { - analyticsEventHandler.send(StakingAnalyticsEvents.ButtonMax(value.cryptoCurrencySymbol)) + analyticsEventHandler.send(StakingAnalyticsEvent.ButtonMax) stateController.update(AmountMaxValueStateTransformer(cryptoCurrencyStatus, yield)) } override fun onCurrencyChangeClick(isFiat: Boolean) { analyticsEventHandler.send( - StakingAnalyticsEvents.AmountSelectCurrency(value.cryptoCurrencySymbol, isFiat), + StakingAnalyticsEvent.AmountSelectCurrency(isFiat), ) stateController.update(AmountCurrencyChangeStateTransformer(cryptoCurrencyStatus, isFiat)) } override fun openValidators() { analyticsEventHandler.send( - StakingAnalyticsEvents.ButtonValidator( + StakingAnalyticsEvent.ButtonValidator( source = StakeScreenSource.Confirmation, - token = value.cryptoCurrencySymbol, ), ) stakingStateRouter.showValidators() @@ -469,18 +459,15 @@ internal class StakingViewModel @Inject constructor( override fun onValidatorSelect(validator: Yield.Validator) { analyticsEventHandler.send( - StakingAnalyticsEvents.ValidatorChosen( - value.cryptoCurrencySymbol, - validator.name, + StakingAnalyticsEvent.ValidatorChosen( + validator = validator.name, ), ) stateController.update(ValidatorSelectChangeTransformer(validator)) } override fun openRewardsValidators() { - analyticsEventHandler.send( - StakingAnalyticsEvents.ButtonRewards(value.cryptoCurrencySymbol), - ) + analyticsEventHandler.send(StakingAnalyticsEvent.ButtonRewards) val rewardsValidators = stateController.value.rewardsValidatorsState as? StakingStates.RewardsValidatorsState.Data val rewards = rewardsValidators?.rewards @@ -488,9 +475,8 @@ internal class StakingViewModel @Inject constructor( onActiveStake(rewards.first()) } else { analyticsEventHandler.send( - StakingAnalyticsEvents.ButtonValidator( + StakingAnalyticsEvent.ButtonValidator( source = StakeScreenSource.Info, - token = value.cryptoCurrencySymbol, ), ) onNextClick(actionTypeToOverwrite = StakingActionCommonType.PENDING_REWARDS) @@ -542,9 +528,8 @@ internal class StakingViewModel @Inject constructor( override fun onActiveStakeAnalytic() { analyticsEventHandler.send( - StakingAnalyticsEvents.ButtonValidator( + StakingAnalyticsEvent.ButtonValidator( source = StakeScreenSource.Info, - token = value.cryptoCurrencySymbol, ), ) } @@ -595,7 +580,7 @@ internal class StakingViewModel @Inject constructor( ).fold( ifLeft = { error -> Timber.e(error.toString()) - analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencySymbol)) + analyticsEventHandler.send(StakingAnalyticsEvent.TransactionError) stateController.update( SetConfirmationStateAssentApprovalTransformer( appCurrencyProvider = Provider { appCurrency }, @@ -617,7 +602,7 @@ internal class StakingViewModel @Inject constructor( ).fold( ifLeft = { error -> Timber.e(error.toString()) - analyticsEventHandler.send(StakingAnalyticsEvents.TransactionError(value.cryptoCurrencySymbol)) + analyticsEventHandler.send(StakingAnalyticsEvent.TransactionError) stateController.update( SetConfirmationStateAssentApprovalTransformer( appCurrencyProvider = Provider { appCurrency }, @@ -747,7 +732,7 @@ internal class StakingViewModel @Inject constructor( } override fun onExploreClick() { - analyticsEventHandler.send(StakingAnalyticsEvents.ButtonExplore) + analyticsEventHandler.send(StakingAnalyticsEvent.ButtonExplore) val confirmationDataState = uiState.value.confirmationState as? StakingStates.ConfirmationState.Data val transactionDoneState = confirmationDataState?.transactionDoneState as? TransactionDoneState.Content val txUrl = transactionDoneState?.txUrl @@ -761,7 +746,7 @@ internal class StakingViewModel @Inject constructor( val transactionDoneState = confirmationDataState?.transactionDoneState as? TransactionDoneState.Content val txUrl = transactionDoneState?.txUrl - analyticsEventHandler.send(StakingAnalyticsEvents.ButtonShare) + analyticsEventHandler.send(StakingAnalyticsEvent.ButtonShare) if (txUrl != null) { vibratorHapticManager.performOneTime(TangemHapticEffect.OneTime.Click) stakingEventFactory.createShareDialog(txUrl = txUrl) @@ -838,10 +823,12 @@ internal class StakingViewModel @Inject constructor( if (!isInitialInfoAnalyticSent) { isInitialInfoAnalyticSent = true val balances = status.value.yieldBalance as? YieldBalance.Data + paramsInterceptorHolder.addParamsInterceptor( + interceptor = StakingParamsInterceptor(status.currency.symbol), + ) analyticsEventHandler.send( - StakingAnalyticsEvents.StakingInfoScreenOpened( + StakingAnalyticsEvent.StakingInfoScreenOpened( validatorsCount = balances?.getValidatorsCount() ?: 0, - token = status.currency.symbol, ), ) } diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 253954e870..2f4b0bdc30 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -88,7 +88,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.17-833" +tangemBlockchainSdk = "release-app_5.17-837" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.17-392" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^