diff --git a/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsHandler.kt index f80aacdc29..d1bef7d01b 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsHandler.kt @@ -11,21 +11,66 @@ import com.tangem.tap.common.analytics.api.ErrorEventHandler import com.tangem.tap.common.analytics.api.ErrorEventLogger import com.tangem.tap.common.analytics.api.SdkErrorEventHandler import com.tangem.tap.common.analytics.api.ShopifyOrderEventHandler +import com.tangem.tap.common.analytics.events.AnalyticsEvent import com.tangem.tap.common.extensions.filterNotNull interface GlobalAnalyticsEventHandler : AnalyticsEventHandler, ErrorEventHandler, SdkErrorEventHandler, - ShopifyOrderEventHandler + ShopifyOrderEventHandler { + + fun attachToAllEvents(key: String, value: String) + + companion object { + fun stub(): GlobalAnalyticsEventHandler { + return object : GlobalAnalyticsEventHandler { + override fun attachToAllEvents(key: String, value: String) {} + override fun handleEvent(event: String, params: Map) {} + override fun handleErrorEvent(error: Throwable, params: Map) {} + override fun handleCardSdkErrorEvent( + error: TangemSdkError, + action: AnalyticsAnOld.ActionToLog, + params: Map, + card: Card?, + ) { + } + + override fun handleBlockchainSdkErrorEvent( + error: BlockchainError, + action: AnalyticsAnOld.ActionToLog, + params: Map, + card: Card?, + ) { + } + + override fun handleShopifyOrderEvent(order: Storefront.Order) {} + } + } + } +} class GlobalAnalyticsHandler( private val analyticsHandlers: List, ) : GlobalAnalyticsEventHandler { + private val attachToAllEventsParams: MutableMap = mutableMapOf() + + override fun attachToAllEvents(key: String, value: String) { + attachToAllEventsParams[key] = value + } + override fun handleEvent(event: String, params: Map) { analyticsHandlers.forEach { it.handleEvent(event, params) } } + override fun handleAnalyticsEvent( + event: AnalyticsEvent, + card: Card?, + blockchain: String?, + ) { + analyticsHandlers.forEach { it.handleAnalyticsEvent(event, card, blockchain) } + } + override fun handleAnalyticsEvent( event: AnalyticsEventAnOld, params: Map, @@ -68,6 +113,12 @@ class GlobalAnalyticsHandler( it.handleShopifyOrderEvent(order) } } + + override fun prepareParams(card: Card?, blockchain: String?, params: Map): Map { + return super.prepareParams(card, blockchain, params).toMutableMap().apply { + putAll(attachToAllEventsParams) + } + } } fun GlobalAnalyticsEventHandler.logWcEvent(event: AnalyticsAnOld.WcAnalyticsEvent) { diff --git a/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt b/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt index 0491d03b80..08e1609e3c 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt @@ -7,6 +7,8 @@ import com.tangem.common.core.TangemSdkError import com.tangem.tap.common.analytics.AnalyticsAnOld import com.tangem.tap.common.analytics.AnalyticsEventAnOld import com.tangem.tap.common.analytics.AnalyticsParamAnOld +import com.tangem.tap.common.analytics.events.AnalyticsEvent +import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.extensions.filterNotNull /** @@ -18,22 +20,40 @@ interface AnalyticsEventHandler { params: Map = emptyMap(), ) + fun handleAnalyticsEvent( + event: AnalyticsEvent, + card: Card? = null, + blockchain: String? = null, + ) { + handleEvent( + event = prepareEventString(event.category, event.event), + params = prepareParams(card, blockchain, event.params), + ) + } + + @Deprecated("Migrate to AnalyticsEvent") fun handleAnalyticsEvent( event: AnalyticsEventAnOld, params: Map = emptyMap(), card: Card? = null, blockchain: String? = null, - ) + ) { + handleEvent(event.event, prepareParams(card, blockchain, params)) + } fun prepareParams( - card: Card?, + card: Card? = null, blockchain: String? = null, params: Map = emptyMap(), ): Map = mapOf( - AnalyticsParamAnOld.FIRMWARE.param to card?.firmwareVersion?.stringValue, - AnalyticsParamAnOld.BATCH_ID.param to card?.batchId, - AnalyticsParamAnOld.BLOCKCHAIN.param to blockchain, + AnalyticsParam.Firmware to card?.firmwareVersion?.stringValue, + AnalyticsParam.BatchId to card?.batchId, + AnalyticsParam.Blockchain to blockchain, ).filterNotNull() + params + + fun prepareEventString(category: String, event: String): String { + return "[$category] $event" + } } interface ErrorEventHandler { diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt index aa8d8439f4..8c69239429 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt @@ -49,4 +49,10 @@ sealed class AnalyticsParam { object LinkedIn : SocialNetwork("LinkedIn") object GitHub : SocialNetwork("GitHub") } + + companion object Key { + const val Blockchain = "blockchain" + const val BatchId = "batch_id" + const val Firmware = "firmware" + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt index 4a57cda71d..b65408b7d5 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt @@ -64,4 +64,13 @@ sealed class Onboarding( class SetupStarted : Twins("Twin Setup Started") class SetupFinished : Twins("Twin Setup Finished") } + + class PinCodeSet: Onboarding("Onboarding", "PIN code set") + class ButtonConnect: Onboarding("Onboarding", "Button - Connect") + class KYCStarted: Onboarding("Onboarding", "KYC started") + class KYCInProgress: Onboarding("Onboarding", "KYC in progress") + class KYCRejected: Onboarding("Onboarding", "KYC rejected") + class ClaimScreenOpened: Onboarding("Onboarding", "Claim screen opened") + class ButtonClaim: Onboarding("Onboarding", "Button - Claim") + class ClaimWasSuccessfully: Onboarding("Onboarding", "Claim was successfully") } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt index dcc0930b4e..27132a1f61 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt @@ -1,7 +1,5 @@ package com.tangem.tap.common.analytics.handlers.amplitude -import com.tangem.common.card.Card -import com.tangem.tap.common.analytics.AnalyticsEventAnOld import com.tangem.tap.common.analytics.api.AnalyticsEventHandler class AmplitudeAnalyticsHandler( @@ -11,13 +9,4 @@ class AmplitudeAnalyticsHandler( override fun handleEvent(event: String, params: Map) { client.logEvent(event, params) } - - override fun handleAnalyticsEvent( - event: AnalyticsEventAnOld, - params: Map, - card: Card?, - blockchain: String?, - ) { - handleEvent(event.event, prepareParams(card, blockchain, params)) - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt index 42ddfb8925..0acfb1dc2f 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt @@ -4,8 +4,6 @@ import com.appsflyer.AFInAppEventParameterName import com.appsflyer.AFInAppEventType import com.shopify.buy3.Storefront import com.tangem.common.Converter -import com.tangem.common.card.Card -import com.tangem.tap.common.analytics.AnalyticsEventAnOld import com.tangem.tap.common.analytics.api.AnalyticsEventHandler import com.tangem.tap.common.analytics.api.ShopifyOrderEventHandler @@ -17,15 +15,6 @@ class AppsFlyerAnalyticsHandler( client.logEvent(event, params) } - override fun handleAnalyticsEvent( - event: AnalyticsEventAnOld, - params: Map, - card: Card?, - blockchain: String?, - ) { - handleEvent(event.event, prepareParams(card, blockchain, params)) - } - override fun handleShopifyOrderEvent(order: Storefront.Order) { handleEvent(ORDER_EVENT, OrderToParamsConverter().convert(order)) } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt index 08404f01f7..3ab6326670 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt @@ -7,7 +7,6 @@ import com.tangem.common.Converter import com.tangem.common.card.Card import com.tangem.common.core.TangemSdkError import com.tangem.tap.common.analytics.AnalyticsAnOld -import com.tangem.tap.common.analytics.AnalyticsEventAnOld import com.tangem.tap.common.analytics.AnalyticsParamAnOld import com.tangem.tap.common.analytics.api.AnalyticsEventHandler import com.tangem.tap.common.analytics.api.ErrorEventHandler @@ -24,15 +23,6 @@ class FirebaseAnalyticsHandler( client.logEvent(event, params) } - override fun handleAnalyticsEvent( - event: AnalyticsEventAnOld, - params: Map, - card: Card?, - blockchain: String?, - ) { - handleEvent(event.name, prepareParams(card, blockchain, params)) - } - override fun handleErrorEvent(error: Throwable, params: Map) { client.logErrorEvent(error, params) } diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt index 76144c6132..15d02907bf 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt @@ -44,8 +44,13 @@ suspend fun WalletManager.safeUpdate(): Result = try { if (exception is BlockchainSdkError.AccountNotFound && amountToCreateAccount != null) { Result.Failure(TapError.WalletManager.NoAccountError(amountToCreateAccount.toString())) } else { - val message = exception.localizedMessage ?: "An error has occurred. Try later" - Result.Failure(TapError.WalletManager.InternalError(message)) + when (exception) { + is BlockchainSdkError -> Result.Failure(exception) + else -> { + val message = exception.cause?.localizedMessage ?: "Unknown error" + Result.Failure(TapError.WalletManager.InternalError(message)) + } + } } } } @@ -72,7 +77,7 @@ fun WalletManager?.getAddressData(): AddressData? { else addressDataList[0] } -fun WalletManager.Companion.stub(): T { +fun WalletManager.Companion.stub(): T { val wallet = Wallet(Blockchain.Unknown, setOf(), Wallet.PublicKey(byteArrayOf(), null, null), setOf()) return object : WalletManager(wallet) { override val currentHost: String = "" diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt index 55b8d535b3..a02172db23 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt @@ -27,7 +27,7 @@ data class GlobalState( val dialog: StateDialog? = null, val exchangeManager: CurrencyExchangeManager = CurrencyExchangeManager.dummy(), val resources: AndroidResources = AndroidResources(), - val analyticsHandler: GlobalAnalyticsEventHandler? = null, + val analyticsHandler: GlobalAnalyticsEventHandler = GlobalAnalyticsEventHandler.stub(), val userCountryCode: String? = null, ) : StateType diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 569c2c4a77..ef916d18c7 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -9,6 +9,7 @@ import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.common.analytics.AnalyticsEventAnOld import com.tangem.tap.common.analytics.AnalyticsParamAnOld import com.tangem.tap.common.analytics.GetCardSourceParamsAnOld +import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.entities.IndeterminateProgressButton import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchOpenUrl @@ -121,6 +122,8 @@ private fun onScanSuccess(scanResponse: ScanResponse) { val tapWalletManager = globalState.tapWalletManager tapWalletManager.updateConfigManager(scanResponse) + globalState.analyticsHandler.attachToAllEvents(AnalyticsParam.BatchId, scanResponse.card.batchId) + store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse)) if (scanResponse.isSaltPay()) { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt index 199b59f22a..2c1dcfad4c 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingSaltPayHelper.kt @@ -19,11 +19,7 @@ class OnboardingSaltPayHelper { manager: SaltPayActivationManager, ): Result { return try { - val status = manager.updateActivationStatus( - amountToClaim = null, - step = SaltPayActivationStep.None, - ).successOr { return it } - + val status = manager.updateActivationStatus(null).successOr { return it } val isRegistrationCase = status.step != SaltPayActivationStep.Finished val isBackupCase = scanResponse.card.backupStatus?.isActive == false Result.Success(isRegistrationCase || isBackupCase) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt index d7e5ff80f7..e103ad4391 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayActivationManager.kt @@ -4,6 +4,7 @@ import android.net.Uri import com.tangem.blockchain.blockchains.ethereum.SignedEthereumTransaction import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType +import com.tangem.blockchain.common.BlockchainSdkError import com.tangem.blockchain.common.TransactionSigner import com.tangem.blockchain.extensions.successOr import com.tangem.common.extensions.guard @@ -21,7 +22,6 @@ import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.UserWalletId import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError -import com.tangem.tap.persistence.SaltPayActivationStorage import java.math.BigDecimal /** @@ -34,7 +34,6 @@ class SaltPayActivationManager( private val kycProvider: KYCProvider, private val paymentologyService: PaymentologyApiService, private val gnosisRegistrator: GnosisRegistrator, - private val registrationStorage: SaltPayActivationStorage, ) { val kycUrlProvider = KYCUrlProvider(walletPublicKey, kycProvider) @@ -43,10 +42,6 @@ class SaltPayActivationManager( private val spendLimitValue: BigDecimal = BigDecimal("100") - fun transactionIsSent(): Boolean { - return registrationStorage.data.transactionsSent - } - suspend fun checkHasGas(): Result { return when (val hasGasResult = gnosisRegistrator.checkHasGas()) { is com.tangem.blockchain.extensions.Result.Success -> if (hasGasResult.data) { @@ -54,7 +49,7 @@ class SaltPayActivationManager( } else { Result.Failure(SaltPayActivationError.NoGas) } - is com.tangem.blockchain.extensions.Result.Failure -> Result.Failure(SaltPayActivationError.NoGas) + is com.tangem.blockchain.extensions.Result.Failure -> Result.Failure(hasGasResult.error as BlockchainSdkError) } } @@ -103,13 +98,7 @@ class SaltPayActivationManager( pin = pinCode, ) - val result = paymentologyService.registerWallet(request) - - registrationStorage.data = registrationStorage.data.copy( - transactionsSent = result is Result.Success, - ) - - return result + return paymentologyService.registerWallet(request) } suspend fun getAmountToClaim(): Result { @@ -166,7 +155,6 @@ class SaltPayActivationManager( kycProvider = SaltPayConfig.stub().kycProvider, paymentologyService = PaymentologyApiService.stub(), gnosisRegistrator = GnosisRegistrator.stub(), - registrationStorage = SaltPayActivationStorage.stub(), cardId = "", cardPublicKey = byteArrayOf(), walletPublicKey = byteArrayOf(), diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt index 87d0c2831d..3b4ed41a05 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.onboarding.products.wallet.saltPay +import com.tangem.blockchain.common.BlockchainSdkError import com.tangem.common.core.TangemSdkError import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.redux.AppDialog @@ -21,7 +22,6 @@ class SaltPayExceptionHandler { } store.dispatchDialogShow(dialog) } - is TangemSdkError -> { when (throwable) { is TangemSdkError.NetworkError -> { @@ -33,8 +33,11 @@ class SaltPayExceptionHandler { } } } + is BlockchainSdkError -> { + store.dispatchDialogShow(AppDialog.SimpleOkErrorDialog(throwable.customMessage)) + } else -> { - val message = throwable.message ?: "SaltPay unknown error" + val message = throwable.localizedMessage ?: "SaltPay unknown error" store.dispatchDialogShow(AppDialog.SimpleOkErrorDialog(message)) } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt index af4a354e4b..446fc6c2ca 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt @@ -10,7 +10,10 @@ import com.tangem.domain.common.extensions.successOr import com.tangem.domain.common.extensions.withMainContext import com.tangem.network.api.paymentology.KYCStatus import com.tangem.network.api.paymentology.RegistrationResponse +import com.tangem.tap.common.analytics.GlobalAnalyticsEventHandler +import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.extensions.isPositive import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.TangemSigner @@ -56,6 +59,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App fun getAppState(): AppState = appState()!! fun getOnboardingWalletState(): OnboardingWalletState = getAppState().onboardingWalletState fun getState(): OnboardingSaltPayState = getOnboardingWalletState().onboardingSaltPayState!! + val analyticsHandler = getAppState().globalState.analyticsHandler when (action) { is OnboardingSaltPayAction.Update -> { @@ -63,21 +67,18 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App val state = getState() scope.launch { - val updateResult = state.saltPayManager.updateActivationStatus( - amountToClaim = state.amountToClaim, - step = state.step, - ).successOr { + val updateResult = state.saltPayManager.updateActivationStatus(state.amountToClaim).successOr { onException(it.error) return@launch } handleInProgress = false - withMainContext { - store.dispatch(OnboardingSaltPayAction.SetStep(updateResult.step)) - } + dispatchOnMain(OnboardingSaltPayAction.SetStep(updateResult.step)) } } is OnboardingSaltPayAction.RegisterCard -> { + analyticsHandler.handleAnalyticsEvent(Onboarding.ButtonConnect()) + handleInProgress = true val state = getState() @@ -126,10 +127,8 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App return@launch } - withMainContext { - handleInProgress = false - store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycIntro)) - } + handleInProgress = false + dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycIntro)) } } is OnboardingSaltPayAction.OpenUtorgKYC -> { @@ -140,20 +139,24 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App } is OnboardingSaltPayAction.RegisterKYC -> { val state = getState() + store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycWaiting)) handleInProgress = true + scope.launch { - registerKYCIfNeeded(state.saltPayManager, state.step).successOr { + Timber.d("saltPayManager.registerKYC()") + state.saltPayManager.registerKYC().successOr { onException(it.error) return@launch } handleInProgress = false - withMainContext { store.dispatch(OnboardingSaltPayAction.Update) } + dispatchOnMain(OnboardingSaltPayAction.Update) } } is OnboardingSaltPayAction.TrySetPin -> { try { assertPinValid(action.pin, getState().pinLength) + analyticsHandler.handleAnalyticsEvent(Onboarding.PinCodeSet()) store.dispatch(OnboardingSaltPayAction.SetPin(action.pin)) store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.CardRegistration)) } catch (error: SaltPayActivationError) { @@ -161,6 +164,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App } } is OnboardingSaltPayAction.Claim -> { + analyticsHandler.handleAnalyticsEvent(Onboarding.ButtonClaim()) val state = getState() handleInProgress = true @@ -191,7 +195,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App onException(it.error) return@launch } - + analyticsHandler.handleAnalyticsEvent(Onboarding.ClaimWasSuccessfully()) dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.ClaimInProgress)) dispatchOnMain(OnboardingSaltPayAction.RefreshClaim) } @@ -202,47 +206,61 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App val state = getState() scope.launch { - val balance = state.saltPayManager.getTokenAmount().successOr { + val tokenAmountValue = state.saltPayManager.getTokenAmount().successOr { SaltPayExceptionHandler.handle(it.error) handleClaimRefreshInProgress = false return@launch } - handleInProgress = false - handleClaimRefreshInProgress = false - dispatchOnMain(OnboardingSaltPayAction.SetTokenBalance(balance)) - dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.Finished)) + if (tokenAmountValue.isPositive()) { + handleInProgress = false + handleClaimRefreshInProgress = false + dispatchOnMain(OnboardingSaltPayAction.SetTokenBalance(tokenAmountValue)) + dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.Finished)) + } else { + handleClaimRefreshInProgress = false + } } } + is OnboardingSaltPayAction.SetStep -> handleAnalytics(analyticsHandler, action.newStep) else -> { /* do nothing, only reduce */ } } } +fun handleAnalytics(analyticsHandler: GlobalAnalyticsEventHandler, step: SaltPayActivationStep?) { + when (step) { + SaltPayActivationStep.None -> {} + SaltPayActivationStep.NoGas -> {} + SaltPayActivationStep.NeedPin -> {} + SaltPayActivationStep.CardRegistration -> {} + SaltPayActivationStep.KycIntro -> {} + SaltPayActivationStep.KycStart -> analyticsHandler.handleAnalyticsEvent(Onboarding.KYCStarted()) + SaltPayActivationStep.KycWaiting -> analyticsHandler.handleAnalyticsEvent(Onboarding.KYCInProgress()) + SaltPayActivationStep.KycReject -> analyticsHandler.handleAnalyticsEvent(Onboarding.KYCRejected()) + SaltPayActivationStep.Claim -> analyticsHandler.handleAnalyticsEvent(Onboarding.ClaimScreenOpened()) + SaltPayActivationStep.ClaimInProgress -> {} + SaltPayActivationStep.Finished -> {} + null -> {} + } +} + data class UpdateResult( val step: SaltPayActivationStep = SaltPayActivationStep.None, val amountToClaim: Amount? = null, ) -suspend fun SaltPayActivationManager.updateActivationStatus( - amountToClaim: Amount?, - step: SaltPayActivationStep, -): Result { +suspend fun SaltPayActivationManager.updateActivationStatus(amountToClaim: Amount?): Result { Timber.d("updateSaltPayStatus") var updateResult = UpdateResult() - checkGasIfNeeded(this, step).successOr { - return Result.Failure(it.error) - - } - registerKYCIfNeeded(this, step).successOr { - return Result.Failure(it.error) - - } val saltPayStep = checkRegistration(this).successOr { return Result.Failure(it.error) + } + checkGasIfNeeded(this, saltPayStep).successOr { + return Result.Failure(it.error) } val fetchedAmountToClaim = getAmountToClaimIfNeeded(this, amountToClaim) @@ -317,10 +335,7 @@ private suspend fun checkGasIfNeeded( step: SaltPayActivationStep, ): Result { Timber.d("checkGasIfNeeded: for step: %s", step) - if (step == SaltPayActivationStep.KycStart || - step == SaltPayActivationStep.KycWaiting || - step == SaltPayActivationStep.Finished - ) { + if (step.ordinal >= SaltPayActivationStep.KycIntro.ordinal) { Timber.d("checkGasIfNeeded: no need to check for step: %s", step) return Result.Success(Unit) } @@ -333,25 +348,6 @@ private suspend fun checkGasIfNeeded( return result } -private suspend fun registerKYCIfNeeded( - saltPayManager: SaltPayActivationManager, - step: SaltPayActivationStep, -): Result { - Timber.d("registerKYCIfNeeded: step: %s", step) - if (step != SaltPayActivationStep.KycStart) { - Timber.d("registerKYCIfNeeded: return Success, because step != KycStart") - return Result.Success(Unit) - } - - withMainContext { - Timber.d("registerKYCIfNeeded: set new step: KycWaiting") - store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycWaiting)) - } - - Timber.d("saltPayManager.registerKYC()") - return saltPayManager.registerKYC() -} - private suspend fun checkRegistration( saltPayManager: SaltPayActivationManager, ): Result { @@ -386,7 +382,7 @@ fun RegistrationResponse.Item.toSaltPayStep(): SaltPayActivationStep { kycStatus != null -> { when (kycStatus) { - KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayActivationStep.KycStart + KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayActivationStep.KycIntro KYCStatus.WAITING_FOR_APPROVAL -> SaltPayActivationStep.KycWaiting KYCStatus.CORRECTION_REQUESTED, KYCStatus.REJECTED -> SaltPayActivationStep.KycReject KYCStatus.APPROVED -> SaltPayActivationStep.Claim diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayState.kt index 419c8fb750..64d23417bd 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayState.kt @@ -17,8 +17,6 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.KYCProvider import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayConfig import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.persistence.SaltPayActivationStorage -import com.tangem.tap.preferencesStorage import com.tangem.tap.store import java.math.BigDecimal @@ -60,7 +58,6 @@ data class OnboardingSaltPayState( scanResponse = scanResponse, gnosisRegistrator = gnosisRegistrator, paymentologyService = store.state.domainNetworks.paymentologyService, - registrationStorage = preferencesStorage.saltPayActivationStorage, kycProvider = saltPayConfig.kycProvider, ) test(scanResponse, gnosisRegistrator) @@ -83,7 +80,6 @@ data class OnboardingSaltPayState( scanResponse: ScanResponse, gnosisRegistrator: GnosisRegistrator, paymentologyService: PaymentologyApiService, - registrationStorage: SaltPayActivationStorage, kycProvider: KYCProvider, ): SaltPayActivationManager { if (!scanResponse.isSaltPay()) { @@ -100,7 +96,6 @@ data class OnboardingSaltPayState( kycProvider = kycProvider, paymentologyService = paymentologyService, gnosisRegistrator = gnosisRegistrator, - registrationStorage = registrationStorage, ) } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt index 6552fbd9d5..a40ace3b49 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt @@ -240,7 +240,7 @@ internal class OnboardingSaltPayView( btnOpenSupportChat.hide() btnKycAction.text = getString(R.string.onboarding_button_kyc_start) btnKycAction.setOnClickListener { - store.dispatch(OnboardingSaltPayAction.Update) + store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycStart)) } progressButton = SaltPayProgressButton(root) } diff --git a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt index 1fad689559..fad5cd8acd 100644 --- a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt +++ b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt @@ -15,7 +15,6 @@ class PreferencesStorage(applicationContext: Application) { val appRatingLaunchObserver: AppRatingLaunchObserver val usedCardsPrefStorage: UsedCardsPrefStorage val fiatCurrenciesPrefStorage: FiatCurrenciesPrefStorage - val saltPayActivationStorage: SaltPayActivationStorage val disclaimerPrefStorage: DisclaimerPrefStorage init { @@ -25,7 +24,6 @@ class PreferencesStorage(applicationContext: Application) { usedCardsPrefStorage.migrate() fiatCurrenciesPrefStorage = FiatCurrenciesPrefStorage(preferences, MoshiJsonConverter.INSTANCE) fiatCurrenciesPrefStorage.migrate() - saltPayActivationStorage = SaltPayActivationPrefStorage(applicationContext, MoshiJsonConverter.INSTANCE) disclaimerPrefStorage = DisclaimerPrefStorage(preferences) } diff --git a/app/src/main/java/com/tangem/tap/persistence/SaltPayActivationPrefStorage.kt b/app/src/main/java/com/tangem/tap/persistence/SaltPayActivationPrefStorage.kt deleted file mode 100644 index 9bfbddc594..0000000000 --- a/app/src/main/java/com/tangem/tap/persistence/SaltPayActivationPrefStorage.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.tangem.tap.persistence - -import android.content.Context -import androidx.core.content.edit -import at.favre.lib.armadillo.ArmadilloSharedPreferences -import com.tangem.common.json.MoshiJsonConverter -import com.tangem.common.services.secure.SecureStorage -import com.tangem.tangem_sdk_new.storage.createEncryptedSharedPreferences - -/** -[REDACTED_AUTHOR] - */ -interface SaltPayActivationStorage { - var data: SaltPayActivationData - - fun reset() - - companion object { - fun stub(): SaltPayActivationStorage = object : SaltPayActivationStorage { - override var data: SaltPayActivationData = SaltPayActivationData() - override fun reset() {} - } - } -} - -data class SaltPayActivationData( - val transactionsSent: Boolean = false, -) - -class SaltPayActivationPrefStorage( - context: Context, - private val converter: MoshiJsonConverter, -) : SaltPayActivationStorage { - - private val storage: ArmadilloSharedPreferences = SecureStorage.createEncryptedSharedPreferences( - context = context, - storageName = "saltpay", - ) - - private var isFetching: Boolean = false - - init { - fetch() - } - - override var data: SaltPayActivationData = SaltPayActivationData() - set(value) { - field = value - if (!isFetching) save() - } - - override fun reset() { - storage.edit(true) { - this.remove(REGISTRATION_DATA_KEY) - data = SaltPayActivationData() - } - } - - private fun save() { - storage.edit(true) { - putString(REGISTRATION_DATA_KEY, converter.toJson(data)) - } - } - - private fun fetch(): SaltPayActivationData { - isFetching = true - - val jsonData = storage.getString(REGISTRATION_DATA_KEY, null) - data = if (jsonData == null) { - SaltPayActivationData() - } else { - converter.fromJson(jsonData) ?: SaltPayActivationData() - } - isFetching = false - - return data - } - - companion object { - private const val REGISTRATION_DATA_KEY = "saltpay_registration_data" - } -} \ No newline at end of file