Skip to content

Commit 520bb89

Browse files
committed
feat(session): record grab times to MixPanel
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent ec3a7a0 commit 520bb89

2 files changed

Lines changed: 110 additions & 34 deletions

File tree

apps/flipcash/shared/session/src/main/kotlin/com/flipcash/app/session/internal/RealSessionController.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import kotlinx.coroutines.launch
8080
import kotlinx.coroutines.suspendCancellableCoroutine
8181
import javax.inject.Inject
8282
import kotlin.coroutines.resume
83+
import kotlin.time.Clock
8384
import kotlin.time.Duration.Companion.milliseconds
8485
import kotlin.time.Duration.Companion.seconds
8586

@@ -118,7 +119,7 @@ class RealSessionController @Inject constructor(
118119
override val billState: StateFlow<BillState>
119120
get() = billController.state
120121

121-
private val scannedRendezvous = mutableListOf<String>()
122+
private val scannedRendezvous = mutableMapOf<String, Long>()
122123

123124
private val giftCardClaimInProgress = MutableStateFlow<String?>(null)
124125

@@ -666,8 +667,6 @@ class RealSessionController @Inject constructor(
666667
vibrator.tick()
667668
}
668669

669-
scannedRendezvous.add(codePayload.rendezvous.publicKey)
670-
671670
trace(
672671
tag = "Session",
673672
message = """
@@ -799,6 +798,8 @@ class RealSessionController @Inject constructor(
799798
}
800799

801800
private fun onCashScanned(payload: OpenCodePayload) {
801+
scannedRendezvous[payload.rendezvous.publicKey] = Clock.System.now().toEpochMilliseconds()
802+
802803
trace(
803804
tag = "Session",
804805
message = "Scanned: ${payload.fiat!!.formatted()} ${payload.fiat!!.currencyCode}"
@@ -809,7 +810,11 @@ class RealSessionController @Inject constructor(
809810
owner = owner,
810811
payload = payload,
811812
onGrabbed = { token, amount ->
812-
analytics.transfer(AnalyticsEvent.GrabBill, amount)
813+
val grabStart = scannedRendezvous[payload.rendezvous.publicKey]
814+
val grabTime = grabStart?.let {
815+
Clock.System.now().toEpochMilliseconds() - it
816+
}
817+
analytics.transfer(AnalyticsEvent.GrabBill, amount, grabTime = grabTime)
813818
BottomBarManager.clear()
814819
toastController.enqueue(amount, isDeposit = true)
815820
showBill(

services/flipcash/src/main/kotlin/com/flipcash/services/analytics/Analytics.kt

Lines changed: 101 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@ interface FlipcashAnalyticsService : AnalyticsService {
2626
fun transfer(
2727
event: AnalyticsEvent.Transfer,
2828
amount: LocalFiat? = null,
29+
grabTime: Long? = null,
2930
successful: Boolean = true,
3031
error: Throwable? = null
3132
)
33+
3234
fun transfer(
3335
event: AnalyticsEvent.Transfer,
3436
fiat: Fiat? = null,
37+
grabTime: Long? = null,
3538
successful: Boolean = true,
3639
error: Throwable? = null
3740
)
@@ -65,10 +68,12 @@ interface FlipcashAnalyticsService : AnalyticsService {
6568
fun connectWallet(
6669
provider: OnRampProvider.UsesDeeplinks
6770
)
71+
6872
fun amountSelectedForWalletTransfer(
6973
provider: OnRampProvider.UsesDeeplinks,
7074
amount: Fiat
7175
)
76+
7277
fun transactionSubmittedToWallet(provider: OnRampProvider.UsesDeeplinks)
7378
fun walletTransactionFailed(provider: OnRampProvider.UsesDeeplinks)
7479
fun walletTransactionCancelled(provider: OnRampProvider.UsesDeeplinks)
@@ -108,13 +113,27 @@ class FlipcashAnalyticsManager @Inject constructor(
108113
track(name = action.value)
109114
}
110115

111-
override fun transfer(event: AnalyticsEvent.Transfer, amount: LocalFiat?, successful: Boolean, error: Throwable?) {
112-
val properties = event.properties(localizedAmount = amount, successful = successful, error = error)
116+
override fun transfer(
117+
event: AnalyticsEvent.Transfer,
118+
amount: LocalFiat?,
119+
grabTime: Long?,
120+
successful: Boolean,
121+
error: Throwable?
122+
) {
123+
val properties =
124+
event.properties(localizedAmount = amount, successful = successful, error = error)
113125
track(event.name, *properties.toList().toTypedArray())
114126
}
115127

116-
override fun transfer(event: AnalyticsEvent.Transfer, fiat: Fiat?, successful: Boolean, error: Throwable?) {
117-
val properties = event.properties(nativeAmount = fiat, successful = successful, error = error)
128+
override fun transfer(
129+
event: AnalyticsEvent.Transfer,
130+
fiat: Fiat?,
131+
grabTime: Long?,
132+
successful: Boolean,
133+
error: Throwable?
134+
) {
135+
val properties =
136+
event.properties(nativeAmount = fiat, successful = successful, error = error)
118137
track(event.name, *properties.toList().toTypedArray())
119138
}
120139

@@ -164,7 +183,8 @@ class FlipcashAnalyticsManager @Inject constructor(
164183
successful: Boolean,
165184
error: Throwable?
166185
) {
167-
val properties = purchaseEvent.properties(nativeAmount = fiat, successful = successful, error = error)
186+
val properties =
187+
purchaseEvent.properties(nativeAmount = fiat, successful = successful, error = error)
168188
track(purchaseEvent.name, *properties.toList().toTypedArray())
169189
}
170190

@@ -174,7 +194,10 @@ class FlipcashAnalyticsManager @Inject constructor(
174194
track(event.name, *properties.toList().toTypedArray())
175195
}
176196

177-
override fun amountSelectedForWalletTransfer(provider: OnRampProvider.UsesDeeplinks, amount: Fiat) {
197+
override fun amountSelectedForWalletTransfer(
198+
provider: OnRampProvider.UsesDeeplinks,
199+
amount: Fiat
200+
) {
178201
val event = AnalyticsEvent.WalletRequestAmount(provider)
179202
val properties = event.properties(
180203
nativeAmount = amount
@@ -217,23 +240,49 @@ class FlipcashAnalyticsManager @Inject constructor(
217240
}
218241
}
219242

220-
class StubFlipcashAnalytics: FlipcashAnalyticsService {
243+
class StubFlipcashAnalytics : FlipcashAnalyticsService {
221244
override fun onAppStart() = Unit
222245
override fun onAppStarted() = Unit
223246
override fun unintentionalLogout() = Unit
224247
override fun action(action: AppAction, source: AppActionSource?) = Unit
225-
override fun transfer(event: AnalyticsEvent.Transfer, amount: LocalFiat?, successful: Boolean, error: Throwable?) = Unit
226-
override fun transfer(event: AnalyticsEvent.Transfer, fiat: Fiat?, successful: Boolean, error: Throwable?) = Unit
248+
override fun transfer(
249+
event: AnalyticsEvent.Transfer,
250+
amount: LocalFiat?,
251+
grabTime: Long?,
252+
successful: Boolean,
253+
error: Throwable?
254+
) = Unit
255+
256+
override fun transfer(
257+
event: AnalyticsEvent.Transfer,
258+
fiat: Fiat?,
259+
grabTime: Long?,
260+
successful: Boolean,
261+
error: Throwable?
262+
) = Unit
263+
227264
override fun paidForAccount(price: Double, currency: CurrencyCode, owner: KeyPair) = Unit
228265
override fun poolOpenedFromDeeplink(id: ID) = Unit
229266
override fun poolCreated(id: ID) = Unit
230267
override fun placedBidInPool(id: ID) = Unit
231268
override fun declaredOutcomeInPool(id: ID) = Unit
232269
override fun openOnramp(openEvent: AnalyticsEvent.OnRampOpenEvent) = Unit
233-
override fun onrampVerification(verificationEvent: AnalyticsEvent.OnRampVerificationEvent) = Unit
234-
override fun onrampPurchase(purchaseEvent: AnalyticsEvent.OnRampPurchaseEvent, fiat: Fiat?, successful: Boolean, error: Throwable?) = Unit
270+
override fun onrampVerification(verificationEvent: AnalyticsEvent.OnRampVerificationEvent) =
271+
Unit
272+
273+
override fun onrampPurchase(
274+
purchaseEvent: AnalyticsEvent.OnRampPurchaseEvent,
275+
fiat: Fiat?,
276+
successful: Boolean,
277+
error: Throwable?
278+
) = Unit
279+
235280
override fun connectWallet(provider: OnRampProvider.UsesDeeplinks) = Unit
236-
override fun amountSelectedForWalletTransfer(provider: OnRampProvider.UsesDeeplinks, amount: Fiat) = Unit
281+
override fun amountSelectedForWalletTransfer(
282+
provider: OnRampProvider.UsesDeeplinks,
283+
amount: Fiat
284+
) = Unit
285+
237286
override fun transactionSubmittedToWallet(provider: OnRampProvider.UsesDeeplinks) = Unit
238287
override fun walletTransactionFailed(provider: OnRampProvider.UsesDeeplinks) = Unit
239288
override fun walletTransactionCancelled(provider: OnRampProvider.UsesDeeplinks) = Unit
@@ -272,6 +321,7 @@ sealed class Action : AppAction {
272321
sealed interface AnalyticsEvent {
273322

274323
val name: String
324+
275325
data class PaidForAccount(
276326
val price: Double,
277327
val currency: CurrencyCode,
@@ -284,18 +334,22 @@ sealed interface AnalyticsEvent {
284334
data object GrabBill : Transfer {
285335
override val name: String = "Grab Bill"
286336
}
337+
287338
data object GiveBill : Transfer {
288339
override val name: String = "Give Bill"
289340
}
341+
290342
data object Withdrawal : Transfer {
291343
override val name: String = "Withdrawal"
292344
}
345+
293346
data class SentCashLink(
294347
val clipboard: Boolean? = null,
295348
val app: String? = null
296349
) : Transfer {
297350
override val name: String = "Send Cash Link"
298351
}
352+
299353
data object ClaimedCashLink : Transfer {
300354
override val name: String = "Receive Cash Link"
301355
}
@@ -320,60 +374,60 @@ sealed interface AnalyticsEvent {
320374
override val name: String = "Pool: Declared Outcome"
321375
}
322376

323-
sealed interface OnRampOpenEvent: AnalyticsEvent {
377+
sealed interface OnRampOpenEvent : AnalyticsEvent {
324378
data object Settings : OnRampOpenEvent {
325379
override val name: String = "Onramp: Opened From Settings"
326380
}
327381

328-
data object Balance: OnRampOpenEvent {
382+
data object Balance : OnRampOpenEvent {
329383
override val name: String = "Onramp: Opened From Balance"
330384
}
331385

332-
data object Give: OnRampOpenEvent {
386+
data object Give : OnRampOpenEvent {
333387
override val name: String = "Onramp: Opened From Give"
334388
}
335389
}
336390

337-
sealed interface OnRampVerificationEvent: AnalyticsEvent {
391+
sealed interface OnRampVerificationEvent : AnalyticsEvent {
338392
data object ShowInfo : OnRampVerificationEvent {
339393
override val name: String = "Onramp: Show Verification Info"
340394
}
341395

342-
data object EnterPhone: OnRampVerificationEvent {
396+
data object EnterPhone : OnRampVerificationEvent {
343397
override val name: String = "Onramp: Show Enter Phone"
344398
}
345399

346-
data object ConfirmPhone: OnRampVerificationEvent {
400+
data object ConfirmPhone : OnRampVerificationEvent {
347401
override val name: String = "Onramp: Show Confirm Phone"
348402
}
349403

350-
data object EnterEmail: OnRampVerificationEvent {
404+
data object EnterEmail : OnRampVerificationEvent {
351405
override val name: String = "Onramp: Show Enter Email"
352406
}
353407

354-
data object ConfirmEmail: OnRampVerificationEvent {
408+
data object ConfirmEmail : OnRampVerificationEvent {
355409
override val name: String = "Onramp: Show Confirm Email"
356410
}
357411
}
358412

359-
sealed interface OnRampPurchaseEvent: AnalyticsEvent {
360-
data object PresetSelected: OnRampPurchaseEvent {
413+
sealed interface OnRampPurchaseEvent : AnalyticsEvent {
414+
data object PresetSelected : OnRampPurchaseEvent {
361415
override val name: String = "Onramp: Amount Selected"
362416
}
363417

364-
data object EnterCustomAmount: OnRampPurchaseEvent {
418+
data object EnterCustomAmount : OnRampPurchaseEvent {
365419
override val name: String = "Onramp: Enter Custom Amount"
366420
}
367421

368-
data object InvokePayment: OnRampPurchaseEvent {
422+
data object InvokePayment : OnRampPurchaseEvent {
369423
override val name: String = "Onramp: Invoke Payment"
370424
}
371425

372-
data object InvokePaymentCustom: OnRampPurchaseEvent {
426+
data object InvokePaymentCustom : OnRampPurchaseEvent {
373427
override val name: String = "Onramp: Invoke Payment Custom"
374428
}
375429

376-
data object Completed: OnRampPurchaseEvent {
430+
data object Completed : OnRampPurchaseEvent {
377431
override val name: String = "Onramp: Completed"
378432
}
379433
}
@@ -386,26 +440,31 @@ sealed interface AnalyticsEvent {
386440
override val name: String = "Wallet: Connect"
387441
}
388442

389-
data class WalletRequestAmount(override val provider: OnRampProvider.UsesDeeplinks) : WalletEvent {
443+
data class WalletRequestAmount(override val provider: OnRampProvider.UsesDeeplinks) :
444+
WalletEvent {
390445
override val name: String = "Wallet: Request Amount"
391446
}
392447

393-
data class WalletSubmitTransaction(override val provider: OnRampProvider.UsesDeeplinks) : WalletEvent {
448+
data class WalletSubmitTransaction(override val provider: OnRampProvider.UsesDeeplinks) :
449+
WalletEvent {
394450
override val name: String = "Wallet: Transactions Submitted"
395451
}
396452

397-
data class WalletTransactionFailed(override val provider: OnRampProvider.UsesDeeplinks) : WalletEvent {
453+
data class WalletTransactionFailed(override val provider: OnRampProvider.UsesDeeplinks) :
454+
WalletEvent {
398455
override val name: String = "Wallet: Transactions Failed"
399456
}
400457

401-
data class WalletTransactionCancelled(override val provider: OnRampProvider.UsesDeeplinks) : WalletEvent {
458+
data class WalletTransactionCancelled(override val provider: OnRampProvider.UsesDeeplinks) :
459+
WalletEvent {
402460
override val name: String = "Wallet: Cancel"
403461
}
404462
}
405463

406464
private fun AnalyticsEvent.properties(
407465
localizedAmount: LocalFiat? = null,
408466
nativeAmount: Fiat? = null,
467+
grabTime: Long? = null,
409468
successful: Boolean? = null,
410469
error: Throwable? = null,
411470
): Map<String, String> {
@@ -437,6 +496,7 @@ private fun AnalyticsEvent.properties(
437496
put("App", event.app)
438497
}
439498
}
499+
440500
AnalyticsEvent.Withdrawal,
441501
AnalyticsEvent.ClaimedCashLink,
442502
AnalyticsEvent.GiveBill,
@@ -455,17 +515,21 @@ private fun AnalyticsEvent.properties(
455515
is AnalyticsEvent.WalletConnect -> {
456516
put("Provider", providerName)
457517
}
518+
458519
is AnalyticsEvent.WalletRequestAmount -> {
459520
put("Provider", providerName)
460521
put("Fiat", nativeAmount?.decimalValue.toString())
461522
put("Currency", nativeAmount?.currencyCode?.name.orEmpty())
462523
}
524+
463525
is AnalyticsEvent.WalletSubmitTransaction -> {
464526
put("Provider", providerName)
465527
}
528+
466529
is AnalyticsEvent.WalletTransactionCancelled -> {
467530
put("Provider", providerName)
468531
}
532+
469533
is AnalyticsEvent.WalletTransactionFailed -> {
470534
put("Provider", providerName)
471535
}
@@ -476,15 +540,18 @@ private fun AnalyticsEvent.properties(
476540
put("Fiat", nativeAmount?.decimalValue.toString())
477541
put("Currency", nativeAmount?.currencyCode?.name.orEmpty())
478542
}
543+
479544
AnalyticsEvent.OnRampPurchaseEvent.EnterCustomAmount -> Unit
480545
AnalyticsEvent.OnRampPurchaseEvent.InvokePayment -> {
481546
put("Fiat", nativeAmount?.decimalValue.toString())
482547
put("Currency", nativeAmount?.currencyCode?.name.orEmpty())
483548
}
549+
484550
AnalyticsEvent.OnRampPurchaseEvent.InvokePaymentCustom -> {
485551
put("Fiat", nativeAmount?.decimalValue.toString())
486552
put("Currency", nativeAmount?.currencyCode?.name.orEmpty())
487553
}
554+
488555
AnalyticsEvent.OnRampPurchaseEvent.PresetSelected -> {
489556
put("Fiat", nativeAmount?.decimalValue.toString())
490557
put("Currency", nativeAmount?.currencyCode?.name.orEmpty())
@@ -497,6 +564,10 @@ private fun AnalyticsEvent.properties(
497564
putAll(nativeAmount.asProperties())
498565
}
499566

567+
if (grabTime != null) {
568+
put("Grab Time", grabTime.toString())
569+
}
570+
500571
if (error != null) {
501572
put("Error", error.message.orEmpty())
502573
}

0 commit comments

Comments
 (0)