From b3e9ad74d7bdd891545b6647e09aceaa802d3f0c Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 29 Jun 2026 11:26:47 -0400 Subject: [PATCH] chore(chat): add analytics to track sent cash and message (success/failures) Signed-off-by: Brandon McAnsh --- .../features/messenger/build.gradle.kts | 1 + .../app/messenger/internal/ChatViewModel.kt | 25 ++++++++++++++++--- .../com/flipcash/app/analytics/Analytics.kt | 5 ++++ .../com/flipcash/app/analytics/Events.kt | 17 +++++++++++++ .../internal/MixpanelAnalyticsDelegate.kt | 4 +++ 5 files changed, 49 insertions(+), 3 deletions(-) diff --git a/apps/flipcash/features/messenger/build.gradle.kts b/apps/flipcash/features/messenger/build.gradle.kts index dc1297ca7..23d0661c6 100644 --- a/apps/flipcash/features/messenger/build.gradle.kts +++ b/apps/flipcash/features/messenger/build.gradle.kts @@ -7,6 +7,7 @@ android { } dependencies { + implementation(project(":apps:flipcash:shared:analytics")) implementation(project(":apps:flipcash:shared:chat")) implementation(project(":apps:flipcash:shared:chat-ui")) implementation(project(":apps:flipcash:shared:amount-entry")) diff --git a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/ChatViewModel.kt b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/ChatViewModel.kt index 1476998d3..432406a89 100644 --- a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/ChatViewModel.kt +++ b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/ChatViewModel.kt @@ -8,6 +8,8 @@ import androidx.paging.PagingData import androidx.paging.cachedIn import androidx.paging.flatMap import androidx.paging.insertSeparators +import com.flipcash.app.analytics.Analytics +import com.flipcash.app.analytics.FlipcashAnalyticsService import com.flipcash.app.contacts.ContactCoordinator import com.flipcash.app.core.AppRoute import com.flipcash.app.core.chat.ChatIdentifier @@ -92,6 +94,7 @@ internal class ChatViewModel @Inject constructor( private val userManager: UserManager, private val resources: ResourceHelper, private val featureFlags: FeatureFlagController, + private val analytics: FlipcashAnalyticsService, ) : BaseViewModel( initialState = State(), updateStateForEvent = updateStateForEvent, @@ -468,8 +471,14 @@ internal class ChatViewModel @Inject constructor( viewModelScope.launch { chatCoordinator.sendMessage(chatId, textToSend) - .onSuccess { trace("message sent successfully") } - .onFailure { trace("message failed to send - ${it.localizedMessage}") } + .onSuccess { + trace("message sent successfully") + analytics.messageSentInChat() + } + .onFailure { cause -> + trace("message failed to send - ${cause.localizedMessage}") + analytics.messageSentInChat(error = cause) + } } } .flowOn(Dispatchers.Main.immediate) @@ -613,12 +622,22 @@ internal class ChatViewModel @Inject constructor( chatCoordinator.refreshFeed() } delay(400.milliseconds) + analytics.transfer( + event = Analytics.Transfer.SentCash, + amount = verifiedFiat.localFiat, + successful = true, + ) dispatchEvent( Dispatchers.Main, Event.SendComplete(amount.localFiat.nativeAmount) ) - }.onFailure { + }.onFailure { cause -> dispatchEvent(Event.SendStateUpdated()) + analytics.transfer( + event = Analytics.Transfer.SentCash, + amount = verifiedFiat.localFiat, + error = cause, + ) BottomBarManager.showError( title = resources.getString(R.string.error_title_cashFailedToSend), message = resources.getString(R.string.error_description_cashFailedToSend), diff --git a/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/Analytics.kt b/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/Analytics.kt index b6f7dd562..14dd41af8 100644 --- a/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/Analytics.kt +++ b/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/Analytics.kt @@ -29,6 +29,7 @@ interface FlipcashAnalyticsService : AnalyticsService { fun openTokenInfo(source: Analytics.TokenInfoSource, mint: Mint) fun buy(method: Analytics.PurchaseMethod, mint: Mint, amount: Fiat, error: Throwable? = null) fun sell(mint: Mint, amount: Fiat, feeAmount: Fiat, error: Throwable? = null) + fun messageSentInChat(error: Throwable? = null) fun deeplinkOpened(url: String) fun deeplinkParsed(type: DeeplinkType?, url: String) fun deeplinkRouted(type: DeeplinkType, error: Throwable? = null) @@ -55,6 +56,8 @@ object Analytics { data object Clipboard : SentCashLink data class App(val name: String) : SentCashLink } + + data object SentCash : Transfer } enum class OnrampSource { Settings, Balance, Give } enum class OnrampVerificationStep { ShowInfo, EnterPhone, ConfirmPhone, EnterEmail, ConfirmEmail } @@ -96,6 +99,8 @@ class StubFlipcashAnalytics : FlipcashAnalyticsService { override fun buy(method: Analytics.PurchaseMethod, mint: Mint, amount: Fiat, error: Throwable?) = Unit override fun sell(mint: Mint, amount: Fiat, feeAmount: Fiat, error: Throwable?) = Unit + override fun messageSentInChat(error: Throwable?) = Unit + override fun deeplinkOpened(url: String) = Unit override fun deeplinkParsed(type: DeeplinkType?, url: String) = Unit override fun deeplinkRouted(type: DeeplinkType, error: Throwable?) = Unit diff --git a/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/Events.kt b/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/Events.kt index 4f1960e32..a4eaca5d4 100644 --- a/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/Events.kt +++ b/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/Events.kt @@ -133,6 +133,22 @@ internal sealed interface AnalyticsEvent { override val name = "Receive Cash Link" } + sealed interface ChatEvent: AnalyticsEvent { + data object SentCash : ChatEvent { + override val name = "Sent Cash" + } + + data class SentMessage( + val error: Throwable? = null + ): ChatEvent { + override val name = "Sent Message" + + override fun toProperties() = buildMap { + error?.let { put("Error", it.message.orEmpty()) } + } + } + } + sealed interface PoolEvent : AnalyticsEvent { val id: ID override fun toProperties() = mapOf("ID" to id.base58) @@ -310,4 +326,5 @@ internal fun Analytics.Transfer.toAnalyticsEvent(): AnalyticsEvent = when (this) is Analytics.Transfer.ClaimedCashLink -> AnalyticsEvent.ClaimedCashLink is Analytics.Transfer.SentCashLink.Clipboard -> AnalyticsEvent.SentCashLink(clipboard = true) is Analytics.Transfer.SentCashLink.App -> AnalyticsEvent.SentCashLink(app = name) + is Analytics.Transfer.SentCash -> AnalyticsEvent.ChatEvent.SentCash } \ No newline at end of file diff --git a/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/internal/MixpanelAnalyticsDelegate.kt b/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/internal/MixpanelAnalyticsDelegate.kt index da5e18456..c9bd30b76 100644 --- a/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/internal/MixpanelAnalyticsDelegate.kt +++ b/apps/flipcash/shared/analytics/src/main/kotlin/com/flipcash/app/analytics/internal/MixpanelAnalyticsDelegate.kt @@ -204,6 +204,10 @@ internal class MixpanelAnalyticsDelegate @Inject constructor( track(AnalyticsEvent.TokenTransactionEvent.Sell(mint, amount, feeAmount, error)) } + override fun messageSentInChat(error: Throwable?) { + track(AnalyticsEvent.ChatEvent.SentMessage(error = error)) + } + override fun deeplinkOpened(url: String) { track(AnalyticsEvent.DeeplinkEvent.Open(url)) }