From c77a309c94b5e1b603c62bb002e2ea3d0a59a339 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 24 Oct 2024 11:49:00 +0300 Subject: [PATCH 1/8] Updated on 2026-08-14 --- core/res/src/main/res/values-de/strings.xml | 6 +++--- core/res/src/main/res/values-uk-rUA/strings.xml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 9fa2f27509..745138a008 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -339,7 +339,7 @@ \nCoinMarketCap Blockchain, auf der die Kryptowährung ursprünglich erstellt wurde Natives Netzwerk - Die Verwendung von nicht nativen Netzwerken für Token ermöglicht eine blockchainübergreifende Interoperabilität, sodass Vermögenswerte in verschiedenen dezentralen Anwendungen und Smart Contracts plattformübergreifend genutzt werden können. Dies erfordert jedoch häufig eine Verwahrstelle oder einen intelligenten Vertrag, um den ursprünglichen Vermögenswert sicher zu verwahren, was zu einer Zentralisierung und einem Kontrahentenrisiko führt. + Die Verwendung nicht-nativer Netzwerke für Token ermöglicht Interoperabilität zwischen Blockchains, sodass Vermögenswerte plattformübergreifend in verschiedenen dezentralen Anwendungen und Smart Contracts genutzt werden können. Dies erfordert jedoch häufig einen Verwahrer oder Smart Contract, um den ursprünglichen Vermögenswert sicher aufzubewahren, was zu Zentralisierung und Kontrahentenrisiken führt. Nicht die ursprüngliche oder primäre Blockchain, in der der Token gehostet wird Nicht-native Netzwerke Netzwerke auswählen @@ -710,7 +710,7 @@ Marktbewertung Metriken Mindestanforderungen - Keine Belohnungen + Keine Belohnungen verfügbar Belohnungen beanspruchen Eine Möglichkeit, Staking-Belohnungen zu erhalten. Es kann automatisch oder manuell beansprucht werden. Belohnungszeitplan @@ -760,7 +760,7 @@ Täglich Alle %s Täglich - Alle %s + Alle %s Tage Jeder Pro Epoche Pro Ära diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index d9837db78c..73f301ed3c 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -520,7 +520,7 @@ Ваша seed-фраза - + слово %d слова %d слів %d слів @@ -741,7 +741,7 @@ Період, який ви повинні чекати після запиту на виведення коштів зі стейкінгу, перш ніж токени стануть доступними. Період блокування Відведений час для активації участі в стейкінгу. - Комісія мережі за схвалення токену, щоб верифікувати, що саме ви даєте дозвіл на використання вашого токена для стейкінгу. + Комісія за схвалення токену, щоб верифікувати, що саме ви дозволяєте використання токена для стейкінгу. Використовуючи функцію стейкінгу, ви погоджуєтесь з %1$s та %2$s Заблоковано Перемістити From a08f570a349de6250e81f72c569defa2fa131c26 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 24 Oct 2024 18:09:17 +0300 Subject: [PATCH 2/8] Updated on 2026-08-14 --- .../staking/impl/analytics/StakingAnalyticsEvents.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 cc612804f3..fde6a9ae23 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 @@ -155,10 +155,10 @@ internal sealed class StakingAnalyticsEvents( event = "Errors", params = mapOf( AnalyticsParam.TOKEN_PARAM to token, - AnalyticsParam.ERROR_TYPE to if (stakeKitError is StakingError.UnknownError) { - stakeKitError.message ?: "Unknown" + if (stakeKitError is StakingError.UnknownError) { + AnalyticsParam.ERROR_DESCRIPTION to (stakeKitError.message ?: "Unknown") } else { - stakeKitError.javaClass.simpleName + AnalyticsParam.ERROR_TYPE to stakeKitError.javaClass.simpleName }, ), ) From f7ff9ca8b216e91205a0afac26cf4cb2013912ed Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 25 Oct 2024 12:06:13 +0300 Subject: [PATCH 3/8] Updated on 2026-08-14 --- .../com/tangem/common/ui/notifications/NotificationsFactory.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt index 36c15ab3c6..ade6bf5a42 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt @@ -66,7 +66,7 @@ object NotificationsFactory { add( NotificationUM.Error.ReserveAmount( BigDecimalFormatter.formatCryptoAmount( - cryptoAmount = sendingAmount, + cryptoAmount = reserveAmount, cryptoCurrency = cryptoCurrency, ), ), From 2eed92d8e98b4668708ae92004b92ac79177081e Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 25 Oct 2024 13:27:52 +0300 Subject: [PATCH 4/8] Updated on 2026-08-14 --- .../domain/tokens/model/warnings/CryptoCurrencyCheck.kt | 1 + .../com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt | 9 +++++++++ .../state/confirm/SendNotificationFactory.kt | 7 +++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyCheck.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyCheck.kt index 04018ed4aa..780c6c48fe 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyCheck.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/warnings/CryptoCurrencyCheck.kt @@ -8,4 +8,5 @@ data class CryptoCurrencyCheck( val reserveAmount: BigDecimal?, val existentialDeposit: BigDecimal?, val utxoAmountLimit: UtxoAmountLimit?, + val isAccountFunded: Boolean, ) \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt index 4e74a21591..f335e654bf 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt @@ -15,11 +15,19 @@ class GetCurrencyCheckUseCase( currencyStatus: CryptoCurrencyStatus, amount: BigDecimal?, fee: BigDecimal?, + recipientAddress: String? = null, ): CryptoCurrencyCheck { val network = currencyStatus.currency.network val dustValue = currencyChecksRepository.getDustValue(userWalletId, network) val reserveAmount = currencyChecksRepository.getReserveAmount(userWalletId, network) val existentialDeposit = currencyChecksRepository.getExistentialDeposit(userWalletId, network) + val isAccountFunded = recipientAddress?.let { + currencyChecksRepository.checkIfAccountFunded( + userWalletId, + network, + recipientAddress, + ) + } ?: false val utxoAmountLimit = if (amount != null && fee != null) { currencyChecksRepository.checkUtxoAmountLimit( userWalletId = userWalletId, @@ -36,6 +44,7 @@ class GetCurrencyCheckUseCase( reserveAmount = reserveAmount, existentialDeposit = existentialDeposit, utxoAmountLimit = utxoAmountLimit, + isAccountFunded = isAccountFunded, ) } } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt index 23f483ef38..48ec5be5b1 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt @@ -45,7 +45,7 @@ import kotlinx.coroutines.flow.map import java.math.BigDecimal @Suppress("LongParameterList", "LargeClass") -internal class SendNotificationFactory constructor( +internal class SendNotificationFactory( private val analyticsEventHandler: AnalyticsEventHandler, private val validateTransactionUseCase: ValidateTransactionUseCase, private val getCurrencyCheckUseCase: GetCurrencyCheckUseCase, @@ -90,11 +90,14 @@ internal class SendNotificationFactory constructor( reduceAmountBy = reduceAmountBy, ) val feeError = (feeState.feeSelectorState as? FeeSelectorState.Error)?.error + + val recipientAddress = state.recipientState?.addressTextField?.value val currencyCheck = getCurrencyCheckUseCase( userWalletId = userWalletId, currencyStatus = cryptoCurrencyStatus, amount = sendingAmount, fee = feeValue, + recipientAddress = recipientAddress, ) buildList { addErrorNotifications( @@ -187,7 +190,7 @@ internal class SendNotificationFactory constructor( reserveAmount = currencyCheck.reserveAmount, sendingAmount = sendingAmount, cryptoCurrency = currency, - isAccountFunded = false, + isAccountFunded = currencyCheck.isAccountFunded, ) } From 03f965673a4d32aa42cfd28bf2fd09a29ec2abde Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 25 Oct 2024 14:57:41 +0300 Subject: [PATCH 5/8] Updated on 2026-08-14 --- .../tap/di/domain/TokensDomainModule.kt | 7 ++- .../domain/tokens/GetCurrencyCheckUseCase.kt | 61 ++++++++++--------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index 5245e5a7ec..545a7a7fe5 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -371,7 +371,10 @@ internal object TokensDomainModule { @Provides @Singleton - fun provideGetCurrencyCheckUseCase(currencyChecksRepository: CurrencyChecksRepository): GetCurrencyCheckUseCase { - return GetCurrencyCheckUseCase(currencyChecksRepository) + fun provideGetCurrencyCheckUseCase( + currencyChecksRepository: CurrencyChecksRepository, + dispatchers: CoroutineDispatcherProvider, + ): GetCurrencyCheckUseCase { + return GetCurrencyCheckUseCase(currencyChecksRepository, dispatchers) } } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt index f335e654bf..aa488b2671 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt @@ -4,10 +4,13 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck import com.tangem.domain.tokens.repository.CurrencyChecksRepository import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.withContext import java.math.BigDecimal class GetCurrencyCheckUseCase( private val currencyChecksRepository: CurrencyChecksRepository, + private val dispatchers: CoroutineDispatcherProvider, ) { suspend operator fun invoke( @@ -17,34 +20,36 @@ class GetCurrencyCheckUseCase( fee: BigDecimal?, recipientAddress: String? = null, ): CryptoCurrencyCheck { - val network = currencyStatus.currency.network - val dustValue = currencyChecksRepository.getDustValue(userWalletId, network) - val reserveAmount = currencyChecksRepository.getReserveAmount(userWalletId, network) - val existentialDeposit = currencyChecksRepository.getExistentialDeposit(userWalletId, network) - val isAccountFunded = recipientAddress?.let { - currencyChecksRepository.checkIfAccountFunded( - userWalletId, - network, - recipientAddress, - ) - } ?: false - val utxoAmountLimit = if (amount != null && fee != null) { - currencyChecksRepository.checkUtxoAmountLimit( - userWalletId = userWalletId, - network = network, - amount = amount, - fee = fee, - ) - } else { - null - } + return withContext(dispatchers.io) { + val network = currencyStatus.currency.network + val dustValue = currencyChecksRepository.getDustValue(userWalletId, network) + val reserveAmount = currencyChecksRepository.getReserveAmount(userWalletId, network) + val existentialDeposit = currencyChecksRepository.getExistentialDeposit(userWalletId, network) + val isAccountFunded = recipientAddress?.let { + currencyChecksRepository.checkIfAccountFunded( + userWalletId, + network, + recipientAddress, + ) + } ?: false + val utxoAmountLimit = if (amount != null && fee != null) { + currencyChecksRepository.checkUtxoAmountLimit( + userWalletId = userWalletId, + network = network, + amount = amount, + fee = fee, + ) + } else { + null + } - return CryptoCurrencyCheck( - dustValue = dustValue, - reserveAmount = reserveAmount, - existentialDeposit = existentialDeposit, - utxoAmountLimit = utxoAmountLimit, - isAccountFunded = isAccountFunded, - ) + CryptoCurrencyCheck( + dustValue = dustValue, + reserveAmount = reserveAmount, + existentialDeposit = existentialDeposit, + utxoAmountLimit = utxoAmountLimit, + isAccountFunded = isAccountFunded, + ) + } } } \ No newline at end of file From 8816b4e20a8f24dd86c55fb7a862401e84e039d9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 25 Oct 2024 19:40:56 +0300 Subject: [PATCH 6/8] Updated on 2026-08-14 --- .../tangem/data/staking/converters/YieldConverter.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/data/staking/src/main/java/com/tangem/data/staking/converters/YieldConverter.kt b/data/staking/src/main/java/com/tangem/data/staking/converters/YieldConverter.kt index 8489a8772d..1ef336d4f8 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/converters/YieldConverter.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/converters/YieldConverter.kt @@ -124,7 +124,7 @@ class YieldConverter( stakedBalance = validatorDTO.stakedBalance, votingPower = validatorDTO.votingPower, preferred = validatorDTO.preferred, - isStrategicPartner = isStrategicPartner(validatorDTO.address), + isStrategicPartner = isStrategicPartner(validatorDTO.address, validatorDTO.name), ) } @@ -177,11 +177,17 @@ class YieldConverter( } } - private fun isStrategicPartner(validatorAddress: String): Boolean = PARTNERS.any { it == validatorAddress } + private fun isStrategicPartner(validatorAddress: String, validatorName: String): Boolean { + return PARTNERS.any { it == validatorAddress } || PARTNERS_NAMES.any { it.equals(validatorName, true) } + } private companion object { val PARTNERS = listOf( "cosmosvaloper1wrx0x9m9ykdhw9sg04v7uljme53wuj03aa5d4f", + "H2tJNyMHnRF6ahCQLQ1sSycM4FGchymuzyYzUqKEuydk", + ) + val PARTNERS_NAMES = listOf( + "Meria", ) } } \ No newline at end of file From 72ea15675654ddb817dd5285f31f367a73d8a5fa Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 28 Oct 2024 11:28:21 +0200 Subject: [PATCH 7/8] Updated on 2026-08-14 --- .../core/analytics/models/AnalyticsParam.kt | 1 + .../core/analytics/di/AnalyticsModule.kt | 7 + .../common/adapter/UnknownEnumMoshiAdapter.kt | 5 - .../model/error/StakeKitErrorResponse.kt | 146 +------------- .../staking/DefaultStakingErrorResolver.kt | 21 +- .../error/StakeKitErrorConverter.kt | 105 +--------- .../data/staking/di/StakingDataModule.kt | 7 +- domain/staking/build.gradle.kts | 1 + .../staking/model/stakekit/StakingError.kt | 92 +-------- .../analytics/StakingAnalyticsEvent.kt | 152 +++++++++++++++ .../impl/analytics/StakingAnalyticsEvents.kt | 179 ------------------ .../analytics/StakingParamsInterceptor.kt | 23 +++ .../analytics/utils/StakingAnalyticSender.kt | 19 +- .../presentation/state/StakingStateRouter.kt | 10 +- .../helpers/StakingFeeTransactionLoader.kt | 2 +- .../state/helpers/StakingTransactionSender.kt | 19 +- .../AddStakingErrorTransformer.kt | 12 +- .../viewmodel/StakingViewModel.kt | 65 +++---- 18 files changed, 276 insertions(+), 590 deletions(-) create mode 100644 domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt delete mode 100644 features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt create mode 100644 features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingParamsInterceptor.kt 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/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt b/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt new file mode 100644 index 0000000000..dbe640d0b0 --- /dev/null +++ b/domain/staking/src/main/java/com/tangem/domain/staking/analytics/StakingAnalyticsEvent.kt @@ -0,0 +1,152 @@ +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 + +sealed class StakingAnalyticsEvent( + event: String, + params: Map = mapOf(), +) : AnalyticsEvent( + category = "Staking", + event = event, + params = params, +) { + + data class StakingInfoScreenOpened( + val validatorsCount: Int, + ) : StakingAnalyticsEvent( + event = "Staking Info Screen Opened", + params = mapOf( + "Validators Count" to validatorsCount.toString(), + ), + ) + + data object WhatIsStaking : StakingAnalyticsEvent( + event = "Link - What Is Staking", + ) + + data object AmountScreenOpened : StakingAnalyticsEvent( + event = "Amount Screen Opened", + ) + + data class ConfirmationScreenOpened( + val validator: String, + val action: StakingActionType, + ) : StakingAnalyticsEvent( + event = "Confirmation Screen Opened", + params = mapOf( + "Validator" to validator, + "Action" to action.asAnalyticName, + ), + ) + + data class StakeInProgressScreenOpened( + val validator: String, + val action: StakingActionType, + ) : StakingAnalyticsEvent( + event = "Stake In Progress Screen Opened", + params = mapOf( + "Validator" to validator, + "Action" to action.asAnalyticName, + ), + ) + + data object RewardScreenOpened : StakingAnalyticsEvent( + event = "Reward Screen Opened", + ) + + data class AmountSelectCurrency( + val isAppCurrency: Boolean, + ) : StakingAnalyticsEvent( + event = "Selected Currency", + params = mapOf( + AnalyticsParam.TYPE to if (isAppCurrency) "App Currency" else "Token", + ), + ) + + data object ButtonMax : StakingAnalyticsEvent( + event = "Button - Max", + ) + + data class ButtonCancel( + val source: StakeScreenSource, + ) : StakingAnalyticsEvent( + event = "Button - Cancel", + params = mapOf( + AnalyticsParam.SOURCE to source.name, + ), + ) + + data class ValidatorChosen( + val validator: String, + ) : StakingAnalyticsEvent( + event = "Validator Chosen", + params = mapOf( + "Validator" to validator, + ), + ) + + data class ButtonValidator( + val source: StakeScreenSource, + ) : StakingAnalyticsEvent( + event = "Button - Validator", + params = mapOf( + AnalyticsParam.SOURCE to source.name, + ), + ) + + data object ButtonRewards : StakingAnalyticsEvent( + event = "Button - Rewards", + ) + + data class ButtonAction( + val action: StakingActionType, + val validator: String, + ) : StakingAnalyticsEvent( + event = "Button - ${action.asAnalyticName}", + params = mapOf( + "Validator" to validator, + ), + ) + + data object ButtonShare : StakingAnalyticsEvent(event = "Button - Share") + + data object ButtonExplore : StakingAnalyticsEvent(event = "Button - Explore") + + data class StakeKitApiError( + val stakingError: StakingError.StakeKitApiError, + ) : StakingAnalyticsEvent( + event = "Errors", + params = buildMap { + addIfValueIsNotNull(AnalyticsParam.ERROR_MESSAGE, stakingError.message) + addIfValueIsNotNull(AnalyticsParam.ERROR_CODE, stakingError.code) + addIfValueIsNotNull(AnalyticsParam.METHOD_NAME, stakingError.methodName) + }, + ) + + 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", + ) +} + +enum class StakeScreenSource { + 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/StakingAnalyticsEvents.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt deleted file mode 100644 index fde6a9ae23..0000000000 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/StakingAnalyticsEvents.kt +++ /dev/null @@ -1,179 +0,0 @@ -package com.tangem.features.staking.impl.analytics - -import com.tangem.core.analytics.models.AnalyticsEvent -import com.tangem.core.analytics.models.AnalyticsParam -import com.tangem.domain.staking.model.stakekit.StakingError -import com.tangem.domain.staking.model.stakekit.action.StakingActionType - -internal sealed class StakingAnalyticsEvents( - event: String, - params: Map = mapOf(), -) : AnalyticsEvent( - category = "Staking", - event = event, - params = params, -) { - - data class StakingInfoScreenOpened( - val validatorsCount: Int, - val token: String, - ) : StakingAnalyticsEvents( - event = "Staking Info Screen Opened", - params = mapOf( - "Validators Count" to validatorsCount.toString(), - AnalyticsParam.TOKEN_PARAM to token, - ), - ) - - data class WhatIsStaking(val token: String) : StakingAnalyticsEvents( - event = "Link - What Is Staking", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), - ) - - data class AmountScreenOpened(val token: String) : StakingAnalyticsEvents( - event = "Amount Screen Opened", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), - ) - - data class ConfirmationScreenOpened( - val token: String, - val validator: String, - val action: StakingActionType, - ) : StakingAnalyticsEvents( - event = "Confirmation Screen Opened", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - "Validator" to validator, - "Action" to action.asAnalyticName, - ), - ) - - 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.asAnalyticName, - ), - ) - - data class RewardScreenOpened(val token: String) : StakingAnalyticsEvents( - event = "Reward Screen Opened", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), - ) - - data class AmountSelectCurrency( - val token: String, - val isAppCurrency: Boolean, - ) : StakingAnalyticsEvents( - 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( - event = "Button - Max", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), - ) - - data class ButtonCancel( - val source: StakeScreenSource, - val token: String, - ) : StakingAnalyticsEvents( - 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( - event = "Validator Chosen", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - "Validator" to validator, - ), - ) - - data class ButtonValidator( - val source: StakeScreenSource, - val token: String, - ) : StakingAnalyticsEvents( - event = "Button - Validator", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - AnalyticsParam.SOURCE to source.name, - ), - ) - - data class ButtonRewards( - val token: String, - ) : StakingAnalyticsEvents( - event = "Button - Rewards", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - ), - ) - - data class ButtonAction( - val action: StakingActionType, - val token: String, - val validator: String, - ) : StakingAnalyticsEvents( - event = "Button - ${action.asAnalyticName}", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - "Validator" to validator, - ), - ) - - data object ButtonShare : StakingAnalyticsEvents(event = "Button - Share") - - data object ButtonExplore : StakingAnalyticsEvents(event = "Button - Explore") - - data class StakekitError( - val token: String, - val stakeKitError: StakingError, - ) : StakingAnalyticsEvents( - event = "Errors", - params = mapOf( - AnalyticsParam.TOKEN_PARAM to token, - if (stakeKitError is StakingError.UnknownError) { - AnalyticsParam.ERROR_DESCRIPTION to (stakeKitError.message ?: "Unknown") - } else { - AnalyticsParam.ERROR_TYPE to stakeKitError.javaClass.simpleName - }, - ), - ) - - data class TransactionError( - val token: String, - ) : StakingAnalyticsEvents( - event = "Error - Transaction Rejected", - params = mapOf(AnalyticsParam.TOKEN_PARAM to token), - ) -} - -enum class StakeScreenSource { - 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, ), ) } From 1f562bc9c3443ab91531ba23506f52ce9187580f Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 29 Oct 2024 00:39:20 +0200 Subject: [PATCH 8/8] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ^