Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public final class WalletConnection {

if let code = url.queryItemValue(for: "errorCode") {
if code == "4001" {
Analytics.walletCancel()
Analytics.track(event: Analytics.WalletEvent.cancel)
pendingSwap = nil

if processing != nil {
Expand Down Expand Up @@ -212,7 +212,7 @@ public final class WalletConnection {
let errorCount = results.count - submittedSignatures.count

if errorCount == 0 {
Analytics.walletTransactionsSubmitted()
Analytics.track(event: Analytics.WalletEvent.transactionsSubmitted)

// If this was a swap transaction, notify server via buy()
if let pending, let firstSignature = submittedSignatures.first, let self {
Expand Down Expand Up @@ -250,7 +250,7 @@ public final class WalletConnection {
}
}
} else {
Analytics.walletTransactionsFailed()
Analytics.track(event: Analytics.WalletEvent.transactionsFailed)
await MainActor.run {
self?.showSomethingWentWrongDialog()
}
Expand Down Expand Up @@ -298,7 +298,7 @@ public final class WalletConnection {
URLQueryItem(name: "nonce", value: nonce)
]

Analytics.walletConnect()
Analytics.track(event: Analytics.WalletEvent.connect)
openExternalWallet(c.url!)
}

Expand Down
3 changes: 3 additions & 0 deletions Flipcash/Core/Screens/Main/BalanceScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ struct BalanceScreen: View {
private func handlePendingCurrencyInfo() {
guard let mint = session.pendingCurrencyInfoMint else { return }

Analytics.tokenInfoOpened(from: .openedFromDeeplink, mint: mint)
selectedMint = mint

// Clear the pending mint
Expand Down Expand Up @@ -162,6 +163,7 @@ struct BalanceScreen: View {
if hasBalances {
ForEach(currencyBalances) { balance in
CurrencyBalanceRow(exchangedBalance: balance) {
Analytics.tokenInfoOpened(from: .openedFromWallet, mint: balance.stored.mint)
selectedMint = balance.stored.mint
}
}
Expand Down Expand Up @@ -199,6 +201,7 @@ struct BalanceScreen: View {
Divider()

Button {
Analytics.tokenInfoOpened(from: .openedFromWallet, mint: reservesBalance.stored.mint)
selectedMint = reservesBalance.stored.mint
} label: {
HStack(spacing: 8) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ struct CurrencyInfoScreen: View {
if !isUSDF {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
Analytics.buttonTapped(name: .shareTokenInfo)
let url = URL(string: "https://app.flipcash.com/token/\(mint.base58)")!
ShareSheet.present(url: url)
} label: {
Expand Down Expand Up @@ -313,6 +314,7 @@ struct CurrencyInfoScreen: View {

if balance.quarks > 0 {
CodeButton(style: .filledSecondary, title: "Sell") {
Analytics.buttonTapped(name: .sell)
isShowingSellAmountEntry = true
}
}
Expand All @@ -329,7 +331,7 @@ struct CurrencyInfoScreen: View {
.navigationDestinationCompat(item: Bindable(walletConnection).processing) { processing in
SwapProcessingScreen(
swapId: processing.swapId,
swapType: .buy,
swapType: .buyWithPhantom,
mint: processing.mint,
amount: processing.amount
)
Expand Down Expand Up @@ -382,10 +384,12 @@ struct CurrencyInfoScreen: View {
FundingSelectionSheet(
reserveBalance: reserveBalance,
onSelectReserves: {
Analytics.buttonTapped(name: .buyWithReserves)
isShowingBuyAmountEntry = true
isShowingFundingSelection = false
},
onSelectPhantom: {
Analytics.buttonTapped(name: .buyWithPhantom)
walletConnection.connectToPhantom()
isShowingFundingSelection = false
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct CurrencyBuyAmountScreen: View {
.navigationDestination(for: CurrencyBuyPath.self) { step in
switch step {
case .processing(let swapId, let mint, let amount):
SwapProcessingScreen(swapId: swapId, swapType: .buy, mint: mint, amount: amount)
SwapProcessingScreen(swapId: swapId, swapType: .buyWithReserves, mint: mint, amount: amount)
.environment(\.dismissParentContainer, {
dismissAction()
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ class SwapProcessingViewModel {
return "This Will Take a Minute"
case .success:
if let exchangedFiat, let mintMetadata {
switch swapType {
case .buy:
if swapType.isBuy {
return "\(exchangedFiat.converted.formatted()) of \(mintMetadata.name)"
case .sell:
} else {
return "\(exchangedFiat.converted.formatted()) of USD Reserves"
}
}
Expand Down Expand Up @@ -65,10 +64,9 @@ class SwapProcessingViewModel {
var navigationTitle: String {
switch displayState {
case .processing:
switch swapType {
case .buy:
if swapType.isBuy {
"Purchasing \(mintMetadata?.name ?? "")"
case .sell:
} else {
"Selling \(mintMetadata?.name ?? "")"
}
case .success:
Expand All @@ -92,7 +90,6 @@ class SwapProcessingViewModel {
private let swapType: SwapType
private let mint: PublicKey
private let amount: ExchangedFiat

// MARK: - Init -

init(swapId: SwapId, swapType: SwapType, mint: PublicKey, amount: ExchangedFiat) {
Expand Down Expand Up @@ -132,10 +129,13 @@ class SwapProcessingViewModel {
switch metadata.state {
case .finalized:
setSwapDetails()
trackTransaction(successful: true)
displayState = .success
case .failed, .cancelled:
trackTransaction(successful: false)
displayState = .failed
case .unknown, .created, .funding, .funded, .submitting, .cancelling:
trackTransaction(successful: false)
displayState = .failed
}
} catch is CancellationError {
Expand All @@ -153,6 +153,17 @@ class SwapProcessingViewModel {
private func setSwapDetails() {
exchangedFiat = amount
}

private func trackTransaction(successful: Bool) {
switch swapType {
case .buyWithReserves:
Analytics.tokenPurchase(method: .purchaseWithReserves, exchangedFiat: amount, successful: successful)
case .buyWithPhantom:
Analytics.tokenPurchase(method: .purchaseWithPhantom, exchangedFiat: amount, successful: successful)
case .sell:
Analytics.tokenSell(exchangedFiat: amount, successful: successful)
}
}
}

// MARK: - DisplayState -
Expand All @@ -168,6 +179,14 @@ extension SwapProcessingViewModel {
// MARK: - SwapType -

enum SwapType {
case buy
case buyWithReserves
case buyWithPhantom
case sell

var isBuy: Bool {
switch self {
case .buyWithReserves, .buyWithPhantom: true
case .sell: false
}
}
}
3 changes: 3 additions & 0 deletions Flipcash/Core/Screens/Main/GiveViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ class GiveViewModel: ObservableObject {

private func presentDeposit() {
depositMint = selectedBalance?.stored.mint
if let depositMint {
Analytics.tokenInfoOpened(from: .openedFromGive, mint: depositMint)
}
}

// MARK: - Errors -
Expand Down
16 changes: 8 additions & 8 deletions Flipcash/Core/Screens/Onboarding/OnboardingViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class OnboardingViewModel: ObservableObject {

navigateToAccessKey()

Analytics.buttonTapped(name: .buttonCreateAccount)
Analytics.buttonTapped(name: .createAccount)
}

func saveToPhotosAction() {
Expand Down Expand Up @@ -114,7 +114,7 @@ class OnboardingViewModel: ObservableObject {
}
}

Analytics.buttonTapped(name: .buttonSaveAccessKey)
Analytics.buttonTapped(name: .saveAccessKey)
}

func wroteDownAction() {
Expand All @@ -129,7 +129,7 @@ class OnboardingViewModel: ObservableObject {
try await self?.completeAccountCreation()
}

Analytics.buttonTapped(name: .buttonWroteAccessKey)
Analytics.buttonTapped(name: .wroteAccessKey)
};
.cancel()
}
Expand Down Expand Up @@ -234,7 +234,7 @@ class OnboardingViewModel: ObservableObject {
completeOnboardingAndLogin()
}

Analytics.buttonTapped(name: .buttonAllowCamera)
Analytics.buttonTapped(name: .allowCamera)
}

func cancelPendingPurchaseAction() {
Expand All @@ -245,7 +245,7 @@ class OnboardingViewModel: ObservableObject {

navigateToRoot()

Analytics.cancelPendingPurchase()
Analytics.track(event: Analytics.GeneralEvent.cancelPendingPurchase)
}

func allowPushPermissionsAction() {
Expand All @@ -256,13 +256,13 @@ class OnboardingViewModel: ObservableObject {
navigateToCameraAccessScreen()
}

Analytics.buttonTapped(name: .buttonAllowPush)
Analytics.buttonTapped(name: .allowPush)
}

func skipPushPermissionsAction() {
navigateToCameraAccessScreen()

Analytics.buttonTapped(name: .buttonSkipPush)
Analytics.buttonTapped(name: .skipPush)
}

// MARK: - Purchase -
Expand Down Expand Up @@ -337,7 +337,7 @@ class OnboardingViewModel: ObservableObject {

sessionAuthenticator.completeLogin(with: initializedAccount)

Analytics.track(event: .completeOnboarding)
Analytics.track(event: Analytics.GeneralEvent.completeOnboarding)
}

// MARK: - Pending Transactions -
Expand Down
12 changes: 6 additions & 6 deletions Flipcash/Core/Screens/Onramp/OnrampViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,13 @@ class OnrampViewModel: ObservableObject {
}

if origin.rawValue < Origin.phone.rawValue, !isPhoneVerified {
Analytics.onrampShowEnterPhone()
Analytics.track(event: Analytics.OnrampEvent.showEnterPhone)
onrampPath.append(.enterPhoneNumber)
return
}

if origin.rawValue < Origin.email.rawValue, !isEmailVerified {
Analytics.onrampShowEnterEmail()
Analytics.track(event: Analytics.OnrampEvent.showEnterEmail)
onrampPath.append(.enterEmail)
return
}
Expand All @@ -308,7 +308,7 @@ class OnrampViewModel: ObservableObject {
isShowingVerificationFlow = false
createOrder()
} else {
Analytics.onrampShowVerificationInfo()
Analytics.track(event: Analytics.OnrampEvent.showVerificationInfo)
isShowingVerificationFlow = true
}
}
Expand Down Expand Up @@ -343,7 +343,7 @@ class OnrampViewModel: ObservableObject {
func customAmountAction() {
selectedPreset = nil
isShowingAmountEntryScreen = true
Analytics.onrampEnterCustomAmount()
Analytics.track(event: Analytics.OnrampEvent.enterCustomAmount)
}

func customAmountEnteredAction() {
Expand Down Expand Up @@ -394,7 +394,7 @@ class OnrampViewModel: ObservableObject {
try await Task.delay(milliseconds: 500)
onrampPath.append(.confirmPhoneNumberCode)

Analytics.onrampShowConfirmPhone()
Analytics.track(event: Analytics.OnrampEvent.showConfirmPhone)

try await Task.delay(milliseconds: 500)
}
Expand Down Expand Up @@ -502,7 +502,7 @@ class OnrampViewModel: ObservableObject {
try await Task.delay(milliseconds: 500)
onrampPath.append(.confirmEmailCode)

Analytics.onrampShowConfirmEmail()
Analytics.track(event: Analytics.OnrampEvent.showConfirmEmail)

try await Task.delay(milliseconds: 500)
}
Expand Down
2 changes: 1 addition & 1 deletion Flipcash/Core/Session/SessionAuthenticator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ final class SessionAuthenticator: ObservableObject {
do {
if let account = try await self?.initialize(using: keyAccount.mnemonic, isRegistration: false) {
self?.completeLogin(with: account)
Analytics.autoLoginComplete()
Analytics.track(event: Analytics.GeneralEvent.autoLoginComplete)
}
} catch {
self?.logout()
Expand Down
18 changes: 13 additions & 5 deletions Flipcash/Utilities/Analytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ import FlipcashCore

typealias AnalyticsValue = MixpanelType

protocol AnalyticsEvent {
var eventName: String { get }
}

extension AnalyticsEvent where Self: RawRepresentable<String> {
var eventName: String { rawValue }
}

enum Analytics {

static func initialize() {
Expand All @@ -28,19 +36,19 @@ enum Analytics {
}
}

static func track(event: Name, properties: [Property: AnalyticsValue]? = nil, error: Error? = nil) {
static func track(event: some AnalyticsEvent, properties: [Property: AnalyticsValue]? = nil, error: Error? = nil) {
var container: [String: AnalyticsValue] = [:]

properties?.forEach { key, value in
container[key.rawValue] = value
}

if let error {
let swiftError = error as NSError
container["Error"] = "\(swiftError.domain).\(error):\(swiftError.code)"
}
track(event.rawValue, properties: container)

track(event.eventName, properties: container)
}

// static func track(_ action: Action, properties: [Property: AnalyticsValue]? = nil) {
Expand Down
Loading