From b18e293e4f6fc83e7e5069b350a46c10c4b334cd Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 24 Jun 2021 14:19:23 +0300 Subject: [PATCH 1/2] Updated on 2026-08-14 --- .../tap/common/analytics/AnalyticsHandler.kt | 10 ++- .../analytics/FirebaseAnalyticsHandler.kt | 70 ++++++++++++++--- .../tap/common/analytics/TangemSdkError.kt | 77 +++++++++++++++++++ .../com/tangem/tap/common/extensions/Map.kt | 4 + .../com/tangem/tap/domain/TangemSdkManager.kt | 9 ++- .../tap/domain/twins/TwinCardsManager.kt | 35 ++++++++- .../walletconnect/WalletConnectSdkHelper.kt | 20 +++++ .../details/redux/DetailsMiddleware.kt | 25 +++++- .../ui/walletconnect/dialogs/WcDialog.kt | 56 ++++++++++++++ .../send/redux/middlewares/SendMiddleware.kt | 17 +++- .../redux/middlewares/WalletMiddleware.kt | 10 +++ 11 files changed, 316 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt create mode 100644 app/src/main/java/com/tangem/tap/common/extensions/Map.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/WcDialog.kt diff --git a/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsHandler.kt index 1dc3586808..30bb8d545d 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsHandler.kt @@ -1,8 +1,16 @@ package com.tangem.tap.common.analytics +import com.tangem.TangemSdkError +import com.tangem.blockchain.common.Blockchain import com.tangem.commands.common.card.Card interface AnalyticsHandler { - fun triggerEvent(event: AnalyticsEvent, card: Card? = null) + fun triggerEvent(event: AnalyticsEvent, card: Card? = null, blockchain: Blockchain? = null) + fun logCardSdkError( + error: TangemSdkError, + actionToLog: FirebaseAnalyticsHandler.ActionToLog, + parameters: Map? = null, + card: Card? = null + ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/FirebaseAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/FirebaseAnalyticsHandler.kt index d1d3ce7a38..5a91215e83 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/FirebaseAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/FirebaseAnalyticsHandler.kt @@ -3,34 +3,84 @@ package com.tangem.tap.common.analytics import android.os.Bundle import androidx.core.os.bundleOf import com.google.firebase.analytics.ktx.analytics +import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.ktx.Firebase +import com.tangem.TangemSdkError +import com.tangem.blockchain.common.Blockchain import com.tangem.commands.common.card.Card +import com.tangem.tap.common.extensions.filterNotNull object FirebaseAnalyticsHandler : AnalyticsHandler { - override fun triggerEvent(event: AnalyticsEvent, card: Card?) { - Firebase.analytics.logEvent(event.event, setCardData(card)) + override fun triggerEvent(event: AnalyticsEvent, card: Card?, blockchain: Blockchain?) { + Firebase.analytics.logEvent(event.event, setData(card, blockchain)) } fun logException(name: String, throwable: Throwable) { Firebase.analytics.logEvent(name, bundleOf( - "message" to (throwable.message ?: "none"), - "cause_message" to (throwable.cause?.message ?: "none"), - "stack_trace" to throwable.stackTraceToString() + "message" to (throwable.message ?: "none"), + "cause_message" to (throwable.cause?.message ?: "none"), + "stack_trace" to throwable.stackTraceToString() )) } - private fun setCardData(card: Card?): Bundle { + override fun logCardSdkError( + error: TangemSdkError, + actionToLog: ActionToLog, + parameters: Map?, + card: Card?, + ) { + if (error is TangemSdkError.UserCancelled) return + + val params = parameters?.toMutableMap() ?: mutableMapOf() + if (card != null) params + getParamsFromCard(card) + params[AnalyticsParam.ACTION] = actionToLog.key + params[AnalyticsParam.ERROR_CODE] = error.code.toString() + params[AnalyticsParam.ERROR_DESCRIPTION] = error.javaClass.simpleName + params[AnalyticsParam.ERROR_KEY] = "TangemSdkError" + + params.forEach { (key, value) -> + FirebaseCrashlytics.getInstance().setCustomKey(key.param, value) + } + val cardError = TangemSdk.map(error) + FirebaseCrashlytics.getInstance().recordException(cardError) + } + + private fun getParamsFromCard(card: Card): Map { + return mapOf( + AnalyticsParam.FIRMWARE to card.firmwareVersion.version, + AnalyticsParam.BATCH_ID to card.cardData?.batchId + ).filterNotNull() + } + + private fun setData(card: Card?, blockchain: Blockchain?): Bundle { if (card == null) return bundleOf() return bundleOf( - AnalyticsParam.BLOCKCHAIN.param to card.cardData?.blockchainName, - AnalyticsParam.BATCH_ID.param to card.cardData?.batchId, - AnalyticsParam.FIRMWARE.param to card.firmwareVersion.version + AnalyticsParam.BLOCKCHAIN.param to (blockchain?.currency ?: card.cardData?.blockchainName), + AnalyticsParam.BATCH_ID.param to card.cardData?.batchId, + AnalyticsParam.FIRMWARE.param to card.firmwareVersion.version ) } - private enum class AnalyticsParam(val param: String) { + enum class AnalyticsParam(val param: String) { BLOCKCHAIN("blockchain"), BATCH_ID("batch_id"), FIRMWARE("firmware"), + ACTION("action"), + ERROR_DESCRIPTION("error_description"), + ERROR_CODE("error_code"), + NEW_SECURITY_OPTION("new_security_option"), + ERROR_KEY("Tangem SDK error key"), + } + + enum class ActionToLog(val key: String) { + Scan("tap_scan_task"), + SendTransaction("send_transaction"), + WalletConnectSign("wallet_connect_personal_sign"), + WalletConnectTransaction("wallet_connect_tx_sign"), + ReadPinSettings("read_pin_settings"), + ChangeSecOptions("change_sec_options"), + CreateWallet("create_wallet"), + PurgeWallet("purge_wallet"), + WriteIssuerData("write_issuer_data"), } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt new file mode 100644 index 0000000000..1c574708e1 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkError.kt @@ -0,0 +1,77 @@ +package com.tangem.tap.common.analytics + +import com.tangem.TangemSdkError + +object TangemSdk { + + // This mapping is performed to group errors in FirebaseCrashlytics. + // At the moment, the errors in Crashlytics can only be grouped by their place of creation (class and line). + fun map(error: TangemSdkError): TangemSdkError { + return when (error) { + is TangemSdkError.TagLost -> TangemSdkError.TagLost() + is TangemSdkError.ExtendedLengthNotSupported -> TangemSdkError.ExtendedLengthNotSupported() + is TangemSdkError.SerializeCommandError -> TangemSdkError.SerializeCommandError() + is TangemSdkError.DeserializeApduFailed -> TangemSdkError.DeserializeApduFailed() + is TangemSdkError.EncodingFailedTypeMismatch -> TangemSdkError.EncodingFailedTypeMismatch( + error.customMessage) + is TangemSdkError.EncodingFailed -> TangemSdkError.EncodingFailed(error.customMessage) + is TangemSdkError.DecodingFailedMissingTag -> TangemSdkError.DecodingFailedMissingTag( + error.customMessage) + is TangemSdkError.DecodingFailedTypeMismatch -> TangemSdkError.DecodingFailedTypeMismatch( + error.customMessage) + is TangemSdkError.DecodingFailed -> TangemSdkError.DecodingFailed(error.customMessage) + is TangemSdkError.InvalidResponse -> TangemSdkError.InvalidResponse() + is TangemSdkError.UnknownStatus -> TangemSdkError.UnknownStatus(error.statusWord) + is TangemSdkError.ErrorProcessingCommand -> TangemSdkError.ErrorProcessingCommand() + is TangemSdkError.InvalidState -> TangemSdkError.InvalidState() + is TangemSdkError.InsNotSupported -> TangemSdkError.InsNotSupported() + is TangemSdkError.InvalidParams -> TangemSdkError.InvalidParams() + is TangemSdkError.NeedEncryption -> TangemSdkError.NeedEncryption() + is TangemSdkError.FileNotFound -> TangemSdkError.FileNotFound() + is TangemSdkError.WalletNotFound -> TangemSdkError.WalletNotFound() + is TangemSdkError.AlreadyPersonalized -> TangemSdkError.AlreadyPersonalized() + is TangemSdkError.CannotBeDepersonalized -> TangemSdkError.CannotBeDepersonalized() + is TangemSdkError.Pin1Required -> TangemSdkError.Pin1Required() + is TangemSdkError.CardReadWrongWallet -> TangemSdkError.CardReadWrongWallet() + is TangemSdkError.CardWithMaxZeroWallets -> TangemSdkError.CardWithMaxZeroWallets() + is TangemSdkError.AlreadyCreated -> TangemSdkError.AlreadyCreated() + is TangemSdkError.WalletIndexExceedsMaxValue -> TangemSdkError.WalletIndexExceedsMaxValue() + is TangemSdkError.MaxNumberOfWalletsCreated -> TangemSdkError.MaxNumberOfWalletsCreated() + is TangemSdkError.WalletIndexNotCorrect -> TangemSdkError.WalletIndexNotCorrect() + is TangemSdkError.PurgeWalletProhibited -> TangemSdkError.PurgeWalletProhibited() + is TangemSdkError.Pin1CannotBeChanged -> TangemSdkError.Pin1CannotBeChanged() + is TangemSdkError.Pin2CannotBeChanged -> TangemSdkError.Pin2CannotBeChanged() + is TangemSdkError.Pin1CannotBeDefault -> TangemSdkError.Pin1CannotBeDefault() + is TangemSdkError.NoRemainingSignatures -> TangemSdkError.NoRemainingSignatures() + is TangemSdkError.EmptyHashes -> TangemSdkError.EmptyHashes() + is TangemSdkError.HashSizeMustBeEqual -> TangemSdkError.HashSizeMustBeEqual() + is TangemSdkError.WalletIsNotCreated -> TangemSdkError.WalletIsNotCreated() + is TangemSdkError.SignHashesNotAvailable -> TangemSdkError.SignHashesNotAvailable() + is TangemSdkError.TooManyHashesInOneTransaction -> TangemSdkError.TooManyHashesInOneTransaction() + is TangemSdkError.ExtendedDataSizeTooLarge -> TangemSdkError.ExtendedDataSizeTooLarge() + is TangemSdkError.NotPersonalized -> TangemSdkError.NotPersonalized() + is TangemSdkError.NotActivated -> TangemSdkError.NotActivated() + is TangemSdkError.WalletIsPurged -> TangemSdkError.WalletIsPurged() + is TangemSdkError.Pin2OrCvcRequired -> TangemSdkError.Pin2OrCvcRequired() + is TangemSdkError.VerificationFailed -> TangemSdkError.VerificationFailed() + is TangemSdkError.DataSizeTooLarge -> TangemSdkError.DataSizeTooLarge() + is TangemSdkError.MissingCounter -> TangemSdkError.MissingCounter() + is TangemSdkError.OverwritingDataIsProhibited -> TangemSdkError.OverwritingDataIsProhibited() + is TangemSdkError.DataCannotBeWritten -> TangemSdkError.DataCannotBeWritten() + is TangemSdkError.MissingIssuerPubicKey -> TangemSdkError.MissingIssuerPubicKey() + is TangemSdkError.CardVerificationFailed -> TangemSdkError.CardVerificationFailed() + is TangemSdkError.WrongPin1 -> TangemSdkError.WrongPin1() + is TangemSdkError.WrongPin2 -> TangemSdkError.WrongPin2() + is TangemSdkError.UnknownError -> TangemSdkError.UnknownError() + is TangemSdkError.UserCancelled -> TangemSdkError.UserCancelled() + is TangemSdkError.Busy -> TangemSdkError.Busy() + is TangemSdkError.MissingPreflightRead -> TangemSdkError.MissingPreflightRead() + is TangemSdkError.WrongCardNumber -> TangemSdkError.WrongCardNumber() + is TangemSdkError.WrongCardType -> TangemSdkError.WrongCardType() + is TangemSdkError.CardError -> TangemSdkError.CardError() + is TangemSdkError.FirmwareNotSupported -> TangemSdkError.FirmwareNotSupported() + is TangemSdkError.WalletError -> TangemSdkError.WalletError() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Map.kt b/app/src/main/java/com/tangem/tap/common/extensions/Map.kt new file mode 100644 index 0000000000..e970306219 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/extensions/Map.kt @@ -0,0 +1,4 @@ +package com.tangem.tap.common.extensions + +fun Map.filterNotNull(): Map = + filter { it.key != null && it.value != null } as Map \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index af401f69bc..2a7810f725 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -16,6 +16,7 @@ import com.tangem.common.extensions.calculateSha256 import com.tangem.tangem_sdk_new.extensions.init import com.tangem.tap.common.analytics.AnalyticsEvent import com.tangem.tap.common.analytics.AnalyticsHandler +import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.domain.extensions.getDefaultWalletIndex import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask import com.tangem.tap.domain.tasks.ScanNoteResponse @@ -37,10 +38,16 @@ class TangemSdkManager(val activity: ComponentActivity) { analyticsHandler: AnalyticsHandler, messageRes: Int? = null ): CompletionResult { analyticsHandler.triggerEvent(AnalyticsEvent.READY_TO_SCAN, null) - return runTaskAsyncReturnOnMain(ScanNoteTask(), + val result = runTaskAsyncReturnOnMain(ScanNoteTask(), initialMessage = Message( activity.getString(messageRes ?: R.string.initial_message_scan_header) )) + if (result is CompletionResult.Failure) { + (result.error as? TangemSdkError)?.let { error -> + analyticsHandler.logCardSdkError(error, FirebaseAnalyticsHandler.ActionToLog.Scan) + } + } + return result } suspend fun createWallet(cardId: String?): CompletionResult { diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt index 43d313f8a6..af088dc421 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt @@ -2,12 +2,14 @@ package com.tangem.tap.domain.twins import com.tangem.KeyPair import com.tangem.Message +import com.tangem.TangemSdkError import com.tangem.blockchain.extensions.Result import com.tangem.blockchain.extensions.SimpleResult import com.tangem.common.CompletionResult import com.tangem.common.extensions.hexToBytes import com.tangem.common.extensions.toHexString import com.tangem.crypto.CryptoUtils +import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.domain.tasks.ScanNoteResponse import com.tangem.tap.tangemSdkManager @@ -28,7 +30,16 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { currentCardPublicKey = response.data.walletPublicKey.toHexString() return SimpleResult.Success } - is CompletionResult.Failure -> return SimpleResult.failure(response.error) + is CompletionResult.Failure -> { + (response.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.CreateWallet, + card = scanNoteResponse.card + ) + } + return SimpleResult.failure(response.error) + } } } @@ -48,7 +59,16 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { secondCardPublicKey = response.data.walletPublicKey.toHexString() return SimpleResult.Success } - is CompletionResult.Failure -> return SimpleResult.failure(response.error) + is CompletionResult.Failure -> { + (response.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.CreateWallet, + card = scanNoteResponse.card + ) + } + return SimpleResult.failure(response.error) + } } } @@ -60,7 +80,16 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { ) return when (response) { is CompletionResult.Success -> Result.Success(response.data) - is CompletionResult.Failure -> Result.failure(response.error) + is CompletionResult.Failure -> { + (response.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.WriteIssuerData, + card = scanNoteResponse.card + ) + } + Result.failure(response.error) + } } } diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index a78b81d7ce..7cff86a035 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -1,6 +1,7 @@ package com.tangem.tap.domain.walletconnect import com.tangem.Message +import com.tangem.TangemSdkError import com.tangem.blockchain.blockchains.ethereum.EthereumGasLoader import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras import com.tangem.blockchain.blockchains.ethereum.EthereumUtils @@ -14,6 +15,7 @@ import com.tangem.commands.SignCommand import com.tangem.commands.wallet.WalletIndex import com.tangem.common.CompletionResult import com.tangem.common.extensions.hexToBytes +import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.common.extensions.toFormattedString import com.tangem.tap.features.details.redux.walletconnect.* import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData @@ -128,6 +130,12 @@ class WalletConnectSdkHelper { HEX_PREFIX + data.walletManager.wallet.recentTransactions.last().hash } is SimpleResult.Failure -> { + (result.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.WalletConnectTransaction, + ) + } Timber.e(result.error) null } @@ -152,6 +160,12 @@ class WalletConnectSdkHelper { HEX_PREFIX + result.data } is CompletionResult.Failure -> { + (result.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.WalletConnectSign, + ) + } Timber.e(result.error.customMessage) null } @@ -208,6 +222,12 @@ class WalletConnectSdkHelper { ) } is CompletionResult.Failure -> { + (result.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.WalletConnectSign, + ) + } Timber.e(result.error.customMessage) null } diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index b66aa958e9..90f75c3efe 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -1,7 +1,9 @@ package com.tangem.tap.features.details.redux +import com.tangem.TangemSdkError import com.tangem.commands.common.network.Result import com.tangem.common.CompletionResult +import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen @@ -90,6 +92,15 @@ class DetailsMiddleware { is CompletionResult.Success -> { store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) } + is CompletionResult.Failure -> { + (result.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.PurgeWallet, + card = store.state.detailsState.card + ) + } + } } } } @@ -148,8 +159,20 @@ class DetailsMiddleware { } store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Success) } - is CompletionResult.Failure, null -> + is CompletionResult.Failure -> { + (result.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error = error, + actionToLog = FirebaseAnalyticsHandler.ActionToLog.ChangeSecOptions, + parameters = mapOf( + FirebaseAnalyticsHandler.AnalyticsParam.NEW_SECURITY_OPTION to + (selectedOption?.name ?: "") + ), + card = store.state.detailsState.card + ) + } store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Failure) + } } } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/WcDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/WcDialog.kt new file mode 100644 index 0000000000..4bbb63e270 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/WcDialog.kt @@ -0,0 +1,56 @@ +package com.tangem.tap.features.details.ui.walletconnect.dialogs + +import android.content.Context +import androidx.appcompat.app.AlertDialog + +class WcDialog { + companion object { + fun create(dialogData: DialogData, context: Context): AlertDialog { + return AlertDialog.Builder(context).apply { + setTitle(dialogData.title) + setMessage(dialogData.message) + setPositiveButton(dialogData.positiveButton.title) { _, _ -> + dialogData.positiveButton.action() + } + setNegativeButton(dialogData.negativeButton.title) { _, _ -> + dialogData.negativeButton.action() + } + setOnDismissListener { dialogData.onDismissAction() } + }.create() + } + } +} + +data class DialogData( + val title: String, + val message: String, + val positiveButton: ButtonData, + val negativeButton: ButtonData, + val onDismissAction: () -> Unit, +) + +data class ButtonData( + val title: String, + val action: () -> Unit, +) + +//class WcDialogMessageBuilder(val messageRes: Int, val data: DialogMessageData? = null) { +// fun build(context: Context): String { +// when (data) { +// null -> context.getString(messageRes) +// } +// } +//} + +interface DialogMessageData + +data class WcTransactionDialogMessageData( + val cardId: String, + val dAppName: String, + val dAppUrl: String, + val amount: String, + val gasAmount: String, + val totalAmount: String, + val balance: String, + val isEnoughFundsToSend: Boolean, +) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index 7dcececcda..9ca7c9ce1c 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.send.redux.middlewares import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.tangem.TangemSdkError import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder import com.tangem.blockchain.common.* @@ -127,7 +128,11 @@ private fun sendTransaction( when (result) { is SimpleResult.Success -> { tangemSdk.config.linkedTerminal = isLinkedTerminal - FirebaseAnalyticsHandler.triggerEvent(AnalyticsEvent.TRANSACTION_IS_SENT, card) + FirebaseAnalyticsHandler.triggerEvent( + event = AnalyticsEvent.TRANSACTION_IS_SENT, + card = card, + blockchain = walletManager.wallet.blockchain + ) dispatch(SendAction.SendSuccess) dispatch(NavigationAction.PopBackTo()) scope.launch(Dispatchers.IO) { @@ -178,6 +183,16 @@ private fun sendTransaction( dispatch(SendAction.SendError(TapError.XmlError.AssetAccountNotCreated)) } else -> { + (result.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.SendTransaction, + mapOf( + FirebaseAnalyticsHandler.AnalyticsParam.BLOCKCHAIN + to walletManager.wallet.blockchain.currency), + card = card, + ) + } Timber.e(throwable) FirebaseCrashlytics.getInstance().recordException(throwable) dispatch(SendAction.SendError(TapError.CustomError(message))) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 183d55ddda..53ce1c2b2a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -3,6 +3,7 @@ package com.tangem.tap.features.wallet.redux.middlewares import android.content.Intent import android.net.Uri import androidx.core.content.ContextCompat +import com.tangem.TangemSdkError import com.tangem.blockchain.common.* import com.tangem.common.CompletionResult import com.tangem.common.extensions.isZero @@ -111,6 +112,15 @@ class WalletMiddleware { globalState.tapWalletManager.onCardScanned(scanNoteResponse) } } + is CompletionResult.Failure -> { + (result.error as? TangemSdkError)?.let { error -> + FirebaseAnalyticsHandler.logCardSdkError( + error, + FirebaseAnalyticsHandler.ActionToLog.CreateWallet, + card = store.state.detailsState.card + ) + } + } } } } From a248994ef032f1e21fee78c4b0862eec2e9ca0e6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 26 Jun 2021 23:11:17 +0300 Subject: [PATCH 2/2] Updated on 2026-08-14 --- .../tap/common/analytics/AnalyticsEvent.kt | 4 ++ .../analytics/FirebaseAnalyticsHandler.kt | 67 +++++++++++++++++-- .../walletconnect/WalletConnectManager.kt | 29 ++++++-- 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsEvent.kt b/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsEvent.kt index 4395bd0922..8ddf2f5ad9 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsEvent.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsEvent.kt @@ -8,4 +8,8 @@ enum class AnalyticsEvent(val event: String) { APP_RATING_DISMISS("dismiss_rate_app_warning"), APP_RATING_NEGATIVE("negative_rate_app_feedback"), APP_RATING_POSITIVE("positive_rate_app_feedback"), + WC_SUCCESS_RESPONSE("wallet_connect_success_response"), + WC_INVALID_REQUEST("wallet_connect_invalid_request"), + WC_NEW_SESSION("wallet_connect_new_session"), + WC_SESSION_DISCONNECTED("wallet_connect_session_disconnected"), } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/FirebaseAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/FirebaseAnalyticsHandler.kt index 5a91215e83..f9aea4c495 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/FirebaseAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/FirebaseAnalyticsHandler.kt @@ -38,8 +38,8 @@ object FirebaseAnalyticsHandler : AnalyticsHandler { params[AnalyticsParam.ERROR_DESCRIPTION] = error.javaClass.simpleName params[AnalyticsParam.ERROR_KEY] = "TangemSdkError" - params.forEach { (key, value) -> - FirebaseCrashlytics.getInstance().setCustomKey(key.param, value) + params.forEach { + FirebaseCrashlytics.getInstance().setCustomKey(it.key.param, it.value) } val cardError = TangemSdk.map(error) FirebaseCrashlytics.getInstance().recordException(cardError) @@ -55,12 +55,55 @@ object FirebaseAnalyticsHandler : AnalyticsHandler { private fun setData(card: Card?, blockchain: Blockchain?): Bundle { if (card == null) return bundleOf() return bundleOf( - AnalyticsParam.BLOCKCHAIN.param to (blockchain?.currency ?: card.cardData?.blockchainName), + AnalyticsParam.BLOCKCHAIN.param to (blockchain?.currency + ?: card.cardData?.blockchainName), AnalyticsParam.BATCH_ID.param to card.cardData?.batchId, AnalyticsParam.FIRMWARE.param to card.firmwareVersion.version ) } + fun logWcEvent(event: WcAnalyticsEvent) { + when (event) { + is WcAnalyticsEvent.Action -> { + + Firebase.analytics.logEvent( + AnalyticsEvent.WC_SUCCESS_RESPONSE.event, bundleOf( + AnalyticsParam.WALLET_CONNECT_ACTION.param to event.action.name + ) + ) + } + is WcAnalyticsEvent.Error -> { + mapOf( + AnalyticsParam.WALLET_CONNECT_ACTION to event.action?.name, + AnalyticsParam.ERROR_DESCRIPTION to event.error.message + ) + .filterNotNull() + .forEach { + FirebaseCrashlytics.getInstance().setCustomKey(it.key.param, it.value) + } + FirebaseCrashlytics.getInstance().recordException(event.error) + } + is WcAnalyticsEvent.InvalidRequest -> + Firebase.analytics.logEvent( + AnalyticsEvent.WC_INVALID_REQUEST.event, bundleOf( + AnalyticsParam.WALLET_CONNECT_REQUEST.param to event.json + ) + ) + is WcAnalyticsEvent.Session -> { + val analyticsEvent = when (event.event) { + WcSessionEvent.Disconnect -> AnalyticsEvent.WC_SESSION_DISCONNECTED + WcSessionEvent.Connect -> AnalyticsEvent.WC_NEW_SESSION + } + Firebase.analytics.logEvent( + analyticsEvent.event, bundleOf( + AnalyticsParam.WALLET_CONNECT_DAPP_URL.param to event.url + ) + ) + } + } + + } + enum class AnalyticsParam(val param: String) { BLOCKCHAIN("blockchain"), BATCH_ID("batch_id"), @@ -70,6 +113,9 @@ object FirebaseAnalyticsHandler : AnalyticsHandler { ERROR_CODE("error_code"), NEW_SECURITY_OPTION("new_security_option"), ERROR_KEY("Tangem SDK error key"), + WALLET_CONNECT_ACTION("wallet_connect_action"), + WALLET_CONNECT_REQUEST("wallet_connect_request"), + WALLET_CONNECT_DAPP_URL("wallet_connect_dapp_url"), } enum class ActionToLog(val key: String) { @@ -83,4 +129,17 @@ object FirebaseAnalyticsHandler : AnalyticsHandler { PurgeWallet("purge_wallet"), WriteIssuerData("write_issuer_data"), } -} \ No newline at end of file + + enum class WcSessionEvent { Disconnect, Connect } + + sealed class WcAnalyticsEvent { + data class Error(val error: Throwable, val action: WcAction?) : + WcAnalyticsEvent() + + data class Session(val event: WcSessionEvent, val url: String?) : WcAnalyticsEvent() + data class Action(val action: WcAction) : WcAnalyticsEvent() + data class InvalidRequest(val json: String?) : WcAnalyticsEvent() + } + + enum class WcAction { PersonalSign, SignTransaction, SendTransaction } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt index 44eece7399..9e11e4920d 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt @@ -3,6 +3,7 @@ package com.tangem.tap.domain.walletconnect import com.tangem.blockchain.common.Blockchain import com.tangem.common.extensions.guard import com.tangem.common.extensions.hexToBytes +import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.details.redux.walletconnect.* @@ -16,10 +17,7 @@ import com.trustwallet.walletconnect.models.ethereum.WCEthereumTransaction import com.trustwallet.walletconnect.models.session.WCSession import com.trustwallet.walletconnect.models.session.WCSessionUpdate import kotlinx.coroutines.launch -import okhttp3.Interceptor -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response +import okhttp3.* import okhttp3.logging.HttpLoggingInterceptor import timber.log.Timber import java.util.* @@ -136,6 +134,10 @@ class WalletConnectManager { } private fun onSessionClosed(session: WCSession) { + FirebaseAnalyticsHandler.logWcEvent( + FirebaseAnalyticsHandler.WcAnalyticsEvent.Session( + FirebaseAnalyticsHandler.WcSessionEvent.Disconnect, sessions[session]?.peerMeta?.url) + ) sessions.remove(session) walletConnectRepository.removeSession(session) store.dispatchOnMain(WalletConnectAction.RemoveSession(session)) @@ -235,6 +237,10 @@ class WalletConnectManager { store.dispatchOnMain(WalletConnectAction.AcceptOpeningSession( sessionData)) } + FirebaseAnalyticsHandler.logWcEvent( + FirebaseAnalyticsHandler.WcAnalyticsEvent.Session( + FirebaseAnalyticsHandler.WcSessionEvent.Connect, peer.url) + ) } } client.onSessionUpdate = { id: Long, update: WCSessionUpdate -> @@ -244,6 +250,11 @@ class WalletConnectManager { } client.onEthSendTransaction = { id: Long, transaction: WCEthereumTransaction -> Timber.d("onEthSendTransaction: $transaction") + FirebaseAnalyticsHandler.logWcEvent( + FirebaseAnalyticsHandler.WcAnalyticsEvent.Action( + FirebaseAnalyticsHandler.WcAction.SendTransaction + ) + ) sessions[client.session]?.toWalletConnectSession()?.let { sessionData -> store.dispatchOnMain(WalletConnectAction.HandleTransactionRequest( transaction = transaction, @@ -256,6 +267,11 @@ class WalletConnectManager { } client.onEthSignTransaction = { id: Long, transaction: WCEthereumTransaction -> Timber.d("onEthSignTransaction: $transaction") + FirebaseAnalyticsHandler.logWcEvent( + FirebaseAnalyticsHandler.WcAnalyticsEvent.Action( + FirebaseAnalyticsHandler.WcAction.SignTransaction + ) + ) sessions[client.session]?.toWalletConnectSession()?.let { sessionData -> store.dispatchOnMain(WalletConnectAction.HandleTransactionRequest( transaction = transaction, @@ -267,6 +283,11 @@ class WalletConnectManager { } client.onEthSign = { id: Long, message: WCEthereumSignMessage -> Timber.d("onEthSign: $message") + FirebaseAnalyticsHandler.logWcEvent( + FirebaseAnalyticsHandler.WcAnalyticsEvent.Action( + FirebaseAnalyticsHandler.WcAction.PersonalSign + ) + ) sessions[client.session]?.toWalletConnectSession()?.let { sessionData -> store.dispatchOnMain(WalletConnectAction.HandlePersonalSignRequest( message,