diff --git a/apps/wallet-mobile/src/features/Discover/useDappConnectorManager.tsx b/apps/wallet-mobile/src/features/Discover/useDappConnectorManager.tsx index d5e6a54c4a..a5c2573127 100644 --- a/apps/wallet-mobile/src/features/Discover/useDappConnectorManager.tsx +++ b/apps/wallet-mobile/src/features/Discover/useDappConnectorManager.tsx @@ -5,6 +5,7 @@ import * as React from 'react' import {InteractionManager} from 'react-native' import {logger} from '../../kernel/logger/logger' +import {useMetrics} from '../../kernel/metrics/metricsManager' import {useWalletNavigation} from '../../kernel/navigation' import {isEmptyString} from '../../kernel/utils' import {cip30LedgerExtensionMaker} from '../../yoroi-wallets/cardano/cip30/cip30-ledger' @@ -27,6 +28,8 @@ export const useDappConnectorManager = () => { const {wallet, meta} = useSelectedWallet() const {navigateToTxReview} = useWalletNavigation() const {tabs, tabActiveIndex} = useBrowser() + const {track} = useMetrics() + const activeTab = tabs[tabActiveIndex] const activeTabUrl = activeTab?.url const activeTabOrigin = activeTabUrl === undefined ? null : new URL(activeTabUrl).origin @@ -38,6 +41,7 @@ export const useDappConnectorManager = () => { const handleSignTx = React.useCallback( ({cbor, manager}: {cbor: string; manager: DappConnector}) => { + track.dappPopupSignTransactionPageViewed() return new Promise((resolve, reject) => { let shouldResolve = true return manager.getDAppList().then(({dapps}) => { @@ -76,11 +80,12 @@ export const useDappConnectorManager = () => { }) }) }, - [activeTabOrigin, navigateToTxReview, navigateTo], + [track, activeTabOrigin, navigateToTxReview, navigateTo], ) const handleSignTxWithHW = React.useCallback( ({cbor, partial, manager}: {cbor: string; partial?: boolean; manager: DappConnector}) => { + track.dappPopupSignTransactionPageViewed() return new Promise((resolve, reject) => { let shouldResolve = true return manager.getDAppList().then(({dapps}) => { @@ -118,7 +123,7 @@ export const useDappConnectorManager = () => { }) }) }, - [activeTabOrigin, navigateToTxReview, navigateTo], + [track, activeTabOrigin, navigateToTxReview, navigateTo], ) return React.useMemo( diff --git a/apps/wallet-mobile/src/features/Initialization/ChooseBiometricLogin/ChooseBiometricLoginScreen.tsx b/apps/wallet-mobile/src/features/Initialization/ChooseBiometricLogin/ChooseBiometricLoginScreen.tsx index bd3b45bab9..5eeaff5d23 100644 --- a/apps/wallet-mobile/src/features/Initialization/ChooseBiometricLogin/ChooseBiometricLoginScreen.tsx +++ b/apps/wallet-mobile/src/features/Initialization/ChooseBiometricLogin/ChooseBiometricLoginScreen.tsx @@ -1,3 +1,4 @@ +import {useFocusEffect} from '@react-navigation/native' import {parseBoolean, useAsyncStorage, useMutationWithInvalidations} from '@yoroi/common' import {useTheme} from '@yoroi/theme' import * as React from 'react' @@ -8,6 +9,7 @@ import {useQuery, UseQueryOptions} from 'react-query' import {Button, ButtonType} from '../../../components/Button/Button' import {Space} from '../../../components/Space/Space' +import {useMetrics} from '../../../kernel/metrics/metricsManager' import {useEnableAuthWithOs} from '../../Auth/common/hooks' import {useStrings} from '../common' import {Biometric} from '../illustrations/Biometric' @@ -15,6 +17,14 @@ import {Biometric} from '../illustrations/Biometric' export const ChooseBiometricLoginScreen = () => { const {styles} = useStyles() const strings = useStrings() + const {track} = useMetrics() + + useFocusEffect( + React.useCallback(() => { + track.onboardingBiometricsPageViewed() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []), + ) const {setScreenShown, isLoading: isScreenShownLoading} = useSetScreenShown() diff --git a/apps/wallet-mobile/src/features/Initialization/DarkThemeAnnouncement/DarkThemeAnnouncement.tsx b/apps/wallet-mobile/src/features/Initialization/DarkThemeAnnouncement/DarkThemeAnnouncement.tsx index c5841ffc61..107d74b32f 100644 --- a/apps/wallet-mobile/src/features/Initialization/DarkThemeAnnouncement/DarkThemeAnnouncement.tsx +++ b/apps/wallet-mobile/src/features/Initialization/DarkThemeAnnouncement/DarkThemeAnnouncement.tsx @@ -1,3 +1,4 @@ +import {useFocusEffect} from '@react-navigation/native' import {parseBoolean, useAsyncStorage, useMutationWithInvalidations} from '@yoroi/common' import {useTheme} from '@yoroi/theme' import React from 'react' @@ -10,6 +11,7 @@ import {useQuery, UseQueryOptions} from 'react-query' import {Button} from '../../../components/Button/Button' import {Space} from '../../../components/Space/Space' import {Text} from '../../../components/Text' +import {useMetrics} from '../../../kernel/metrics/metricsManager' import {useWalletNavigation} from '../../../kernel/navigation' import {DarkThemeIlustration} from '../illustrations/DarkThemeIlustration' import {LightThemeIlustration} from '../illustrations/LightThemeIlustration' @@ -18,10 +20,18 @@ export const DarkThemeAnnouncement = () => { const {styles} = useStyles() const strings = useStrings() const {isDark} = useTheme() + const {track} = useMetrics() const {setScreenShown, isLoading: isSetScreenShownLoading} = useSetScreenShown() const scrollViewRef = React.useRef(null) + useFocusEffect( + React.useCallback(() => { + track.onboardingThemePageViewed() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []), + ) + React.useEffect(() => { const timeout = setTimeout(() => { scrollViewRef.current?.flashScrollIndicators() @@ -67,8 +77,12 @@ export const DarkThemeAnnouncement = () => { const Toggle = () => { const {styles, color} = useStyles() const {isLight, isDark, selectThemeName} = useTheme() + const {track} = useMetrics() - const handleOnValueChange = () => selectThemeName(isLight ? 'default-dark' : 'default-light') + const handleOnValueChange = () => { + selectThemeName(isLight ? 'default-dark' : 'default-light') + track.themeSelected({theme: isLight ? 'dark' : 'light'}) + } return ( diff --git a/apps/wallet-mobile/src/features/Initialization/InitializationNavigator.tsx b/apps/wallet-mobile/src/features/Initialization/InitializationNavigator.tsx index 0df5f295a7..6f16cc5084 100644 --- a/apps/wallet-mobile/src/features/Initialization/InitializationNavigator.tsx +++ b/apps/wallet-mobile/src/features/Initialization/InitializationNavigator.tsx @@ -1,7 +1,9 @@ +import {useFocusEffect} from '@react-navigation/native' import {createStackNavigator} from '@react-navigation/stack' import {useTheme} from '@yoroi/theme' import React from 'react' +import {useMetrics} from '../../kernel/metrics/metricsManager' import {defaultStackNavigationOptions, InititalizationRoutes} from '../../kernel/navigation' import {useAuth} from '../Auth/AuthProvider' import {EnableLoginWithPin} from '../Auth/EnableLoginWithPin' @@ -60,6 +62,14 @@ export const InitializationNavigator = () => { const CreatePinScreenWrapper = () => { const {login} = useAuth() + const {track} = useMetrics() + + useFocusEffect( + React.useCallback(() => { + track.onboardingPinCodePageViewed() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []), + ) return } diff --git a/apps/wallet-mobile/src/features/Settings/useCases/changeAppSettings/ChangeTheme/ThemePickerItem.tsx b/apps/wallet-mobile/src/features/Settings/useCases/changeAppSettings/ChangeTheme/ThemePickerItem.tsx index 337e58a73f..1fa1745f9a 100644 --- a/apps/wallet-mobile/src/features/Settings/useCases/changeAppSettings/ChangeTheme/ThemePickerItem.tsx +++ b/apps/wallet-mobile/src/features/Settings/useCases/changeAppSettings/ChangeTheme/ThemePickerItem.tsx @@ -6,6 +6,7 @@ import {StyleSheet, TouchableOpacity, View} from 'react-native' import {Icon} from '../../../../../components/Icon' import {Text} from '../../../../../components/Text' import {themeNames} from '../../../../../kernel/i18n/global-messages' +import {useMetrics} from '../../../../../kernel/metrics/metricsManager' import {useThemeStorageMaker} from '../../../../../yoroi-wallets/hooks' type Props = { @@ -18,8 +19,10 @@ export const ThemePickerItem = ({title, selectTheme, setLocalTheme}: Props) => { const {colors} = useStyles() const strings = useStrings() const themeStorage = useThemeStorageMaker() + const {track} = useMetrics() const handleSelectTheme = (theme: SupportedThemes) => { + track.themeSelected({theme: theme === 'default-light' ? 'light' : theme === 'default-dark' ? 'dark' : 'auto'}) setLocalTheme(theme) selectTheme(theme) } diff --git a/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/CheckNanoXScreen.tsx b/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/CheckNanoXScreen.tsx index ab81cec717..a9b379356a 100644 --- a/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/CheckNanoXScreen.tsx +++ b/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/CheckNanoXScreen.tsx @@ -1,4 +1,4 @@ -import {useNavigation} from '@react-navigation/native' +import {useFocusEffect, useNavigation} from '@react-navigation/native' import {useSetupWallet} from '@yoroi/setup-wallet' import {useTheme} from '@yoroi/theme' import React from 'react' @@ -11,6 +11,7 @@ import {Button} from '../../../../components/Button/Button' import {Space} from '../../../../components/Space/Space' import {StepperProgress} from '../../../../components/StepperProgress/StepperProgress' import {Text} from '../../../../components/Text' +import {useMetrics} from '../../../../kernel/metrics/metricsManager' import {SetupWalletRouteNavigation} from '../../../../kernel/navigation' import {useStrings} from '../../common/useStrings' import {LedgerCheckIllustration} from '../../illustrations/LedgerCheckIllustration' @@ -18,11 +19,19 @@ import {LedgerCheckIllustration} from '../../illustrations/LedgerCheckIllustrati export const CheckNanoXScreen = () => { const strings = useStrings() const styles = useStyles() + const {track} = useMetrics() const navigation = useNavigation() const onContinue = () => navigation.navigate('setup-wallet-connect-nano-x') const {useUSB} = useSetupWallet() + useFocusEffect( + React.useCallback(() => { + track.connectWalletCheckPageViewed() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []), + ) + const commonRequirements = [strings.appInstalled, strings.appOpened] const usbRequirements = [strings.haveOTGAdapter, strings.usbAlwaysConnected, ...commonRequirements] const bleRequirements = [ diff --git a/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/ConnectNanoXScreen.tsx b/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/ConnectNanoXScreen.tsx index f9c428370f..314dc26dac 100644 --- a/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/ConnectNanoXScreen.tsx +++ b/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/ConnectNanoXScreen.tsx @@ -1,4 +1,4 @@ -import {useNavigation} from '@react-navigation/native' +import {useFocusEffect, useNavigation} from '@react-navigation/native' import {useSetupWallet} from '@yoroi/setup-wallet' import {useTheme} from '@yoroi/theme' import {HW} from '@yoroi/types' @@ -12,6 +12,7 @@ import {StepperProgress} from '../../../../components/StepperProgress/StepperPro import {showErrorDialog} from '../../../../kernel/dialogs' import {errorMessages} from '../../../../kernel/i18n/global-messages' import {LocalizableError} from '../../../../kernel/i18n/LocalizableError' +import {useMetrics} from '../../../../kernel/metrics/metricsManager' import {SetupWalletRouteNavigation} from '../../../../kernel/navigation' import {LedgerConnect} from '../../../../legacy/HW' import {getHWDeviceInfo} from '../../../../yoroi-wallets/cardano/hw/hw' @@ -33,11 +34,19 @@ export const ConnectNanoXScreen = ({defaultDevices}: Props) => { const {styles} = useStyles() const {walletManager} = useWalletManager() const {openModal} = useModal() + const {track} = useMetrics() const navigation = useNavigation() const {hwDeviceInfoChanged, walletImplementation, useUSB} = useSetupWallet() + useFocusEffect( + React.useCallback(() => { + track.connectWalletConnectPageViewed() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []), + ) + const onSuccess = (hwDeviceInfo: HW.DeviceInfo) => { hwDeviceInfoChanged(hwDeviceInfo) diff --git a/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/SaveNanoXScreen.tsx b/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/SaveNanoXScreen.tsx index 9d80a28c77..2165835620 100644 --- a/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/SaveNanoXScreen.tsx +++ b/apps/wallet-mobile/src/features/SetupWallet/useCases/RestoreHwWallet/SaveNanoXScreen.tsx @@ -1,4 +1,4 @@ -import {useNavigation} from '@react-navigation/native' +import {useFocusEffect, useNavigation} from '@react-navigation/native' import {useAsyncStorage} from '@yoroi/common' import {Blockies} from '@yoroi/identicon' import {useSetupWallet} from '@yoroi/setup-wallet' @@ -73,6 +73,13 @@ export const SaveNanoXScreen = () => { const {walletImplementation, hwDeviceInfo, accountVisual, walletIdChanged} = useSetupWallet() + useFocusEffect( + React.useCallback(() => { + track.connectWalletDetailsPageViewed() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []), + ) + if (!hwDeviceInfo) throw new Error('no hwDeviceInfo') const {plate, seed} = walletManager.checksum(hwDeviceInfo.bip44AccountPublic) @@ -89,6 +96,7 @@ export const SaveNanoXScreen = () => { } track.restoreWalletDetailsSettled() + track.connectWalletDetailsSubmitted() navigation.navigate('setup-wallet-preparing-wallet') }, diff --git a/apps/wallet-mobile/src/kernel/metrics/ampli/index.ts b/apps/wallet-mobile/src/kernel/metrics/ampli/index.ts index 51b8a6fe91..72d14da2d3 100644 --- a/apps/wallet-mobile/src/kernel/metrics/ampli/index.ts +++ b/apps/wallet-mobile/src/kernel/metrics/ampli/index.ts @@ -498,6 +498,18 @@ export interface SettingsInAppNotificationsStatusUpdatedProperties { status?: 'enabled' | 'disabled' } +export interface StakingCenterDelegationSubmittedProperties { + /** + * The amount of ADA that the user will be exchanging. + * + * | Rule | Value | + * |---|---| + * | Type | number | + */ + ada_amount?: number + staking_pool?: string +} + export interface SwapAssetFromChangedProperties { /** * Displaying the asset that the user chose to trade with. @@ -900,6 +912,10 @@ export class BuyAdaSuccessRedirect implements BaseEvent { event_type = 'Buy Ada Success Redirect' } +export class ClaimAdaTransactionInitiated implements BaseEvent { + event_type = 'Claim Ada Transaction Initiated' +} + export class ClaimAdaTransactionSettled implements BaseEvent { event_type = 'Claim Ada Transaction Settled' @@ -1340,6 +1356,14 @@ export class StakingCenterDelegationInitiated implements BaseEvent { event_type = 'Staking Center Delegation Initiated' } +export class StakingCenterDelegationSubmitted implements BaseEvent { + event_type = 'Staking Center Delegation Submitted' + + constructor(public event_properties?: StakingCenterDelegationSubmittedProperties) { + this.event_properties = event_properties + } +} + export class StakingCenterPageViewed implements BaseEvent { event_type = 'Staking Center Page Viewed' } @@ -1571,7 +1595,7 @@ export class Ampli { * * [View in Tracking Plan](https://data.amplitude.com/emurgo/Yoroi/events/main/latest/Assets%20Page%20Viewed) * - * This event tracks when a user views the Assets page. + * This event tracks when a user views the Assets page. * On mobile is available on the wallet page (First item from main menu) in the assets tab. * * @param options Amplitude event options. @@ -1597,6 +1621,21 @@ export class Ampli { return this.track(new BuyAdaSuccessRedirect(), options); } + /** + * Claim Ada Transaction Initiated + * + * [View in Tracking Plan](https://data.amplitude.com/emurgo/Yoroi/events/main/latest/Claim%20Ada%20Transaction%20Initiated) + * + * This event tracks when a user starts the funne to claim staking rewards in the delegation center. + * + * @param options Amplitude event options. + */ + claimAdaTransactionInitiated( + options?: EventOptions, + ) { + return this.track(new ClaimAdaTransactionInitiated(), options); + } + /** * Claim Ada Transaction Settled * @@ -1788,11 +1827,11 @@ export class Ampli { * * [View in Tracking Plan](https://data.amplitude.com/emurgo/Yoroi/events/main/latest/Create%20Wallet%20Select%20Method%20Page%20Viewed) * - * This event tracks when a user views the page where they can select the method to create a wallet: + * This event tracks when a user views the page where they can select the method to create a wallet: * - * \* Create new wallet + * \* Create new wallet * - * \* Restore existing wallet + * \* Restore existing wallet * * This event tracks when a user views the page where they can select the method to create a wallet\* Connect hardware wallet * @@ -2289,7 +2328,7 @@ export class Ampli { * * [View in Tracking Plan](https://data.amplitude.com/emurgo/Yoroi/events/main/latest/Menu%20Page%20Viewed) * - * This event is triggered when a user views the menu page within the application. Only available on Mobile. + * This event is triggered when a user views the menu page within the application. Only available on Mobile. * The menu page is accesible via the bottom navigation page (last item on the right) * * @param options Amplitude event options. @@ -2800,9 +2839,9 @@ export class Ampli { * * [View in Tracking Plan](https://data.amplitude.com/emurgo/Yoroi/events/main/latest/Send%20Select%20Asset%20Updated) * - * When an user update the tokens selection on "amount" step: - * \- Add - * \- Remove + * When an user update the tokens selection on "amount" step: + * \- Add + * \- Remove * \- Updated * * @param properties The event's properties (e.g. asset_count) @@ -2896,6 +2935,23 @@ export class Ampli { return this.track(new StakingCenterDelegationInitiated(), options); } + /** + * Staking Center Delegation Submitted + * + * [View in Tracking Plan](https://data.amplitude.com/emurgo/Yoroi/events/main/latest/Staking%20Center%20Delegation%20Submitted) + * + * Event indicating that a user has submitted a delegation in the staking center. + * + * @param properties The event's properties (e.g. ada_amount) + * @param options Amplitude event options. + */ + stakingCenterDelegationSubmitted( + properties?: StakingCenterDelegationSubmittedProperties, + options?: EventOptions, + ) { + return this.track(new StakingCenterDelegationSubmitted(properties), options); + } + /** * Staking Center Page Viewed * diff --git a/apps/wallet-mobile/src/kernel/metrics/metricsManager.test.tsx b/apps/wallet-mobile/src/kernel/metrics/metricsManager.test.tsx index e694bba4e3..5819ea740d 100644 --- a/apps/wallet-mobile/src/kernel/metrics/metricsManager.test.tsx +++ b/apps/wallet-mobile/src/kernel/metrics/metricsManager.test.tsx @@ -140,6 +140,25 @@ const mockAmpli = { networkSelected: jest.fn(), + onboardingPinCodePageViewed: jest.fn(), + onboardingBiometricsPageViewed: jest.fn(), + onboardingThemePageViewed: jest.fn(), + + connectWalletCheckPageViewed: jest.fn(), + connectWalletConnectPageViewed: jest.fn(), + connectWalletDetailsPageViewed: jest.fn(), + connectWalletDetailsSubmitted: jest.fn(), + + stakingCenterDelegationInitiated: jest.fn(), + stakingCenterDelegationSubmitted: jest.fn(), + + claimAdaTransactionInitiated: jest.fn(), + claimAdaTransactionSubmitted: jest.fn(), + + themeSelected: jest.fn(), + + dappPopupSignTransactionPageViewed: jest.fn(), + inAppNotificationOpened: jest.fn(), inAppNotificationClosed: jest.fn(), inAppNotificationViewed: jest.fn(), @@ -305,6 +324,25 @@ describe('makeMetricsManager', () => { metricsManager.track.networkSelected({to_network: 'preprod', from_network: 'preview'}) + metricsManager.track.onboardingPinCodePageViewed() + metricsManager.track.onboardingBiometricsPageViewed() + metricsManager.track.onboardingThemePageViewed() + + metricsManager.track.connectWalletCheckPageViewed() + metricsManager.track.connectWalletConnectPageViewed() + metricsManager.track.connectWalletDetailsPageViewed() + metricsManager.track.connectWalletDetailsSubmitted() + + metricsManager.track.stakingCenterDelegationInitiated() + metricsManager.track.stakingCenterDelegationSubmitted() + + metricsManager.track.claimAdaTransactionInitiated() + metricsManager.track.claimAdaTransactionSubmitted() + + metricsManager.track.themeSelected({theme: 'auto'}) + + metricsManager.track.dappPopupSignTransactionPageViewed() + metricsManager.track.inAppNotificationOpened({type: 'tx_received'}) metricsManager.track.inAppNotificationClosed({type: 'tx_received'}) metricsManager.track.inAppNotificationViewed() @@ -431,6 +469,25 @@ describe('makeMetricsManager', () => { expect(mockAmpli.networkSelected).toHaveBeenCalledWith({to_network: 'preprod', from_network: 'preview'}) + expect(mockAmpli.onboardingPinCodePageViewed).toHaveBeenCalled() + expect(mockAmpli.onboardingBiometricsPageViewed).toHaveBeenCalled() + expect(mockAmpli.onboardingThemePageViewed).toHaveBeenCalled() + + expect(mockAmpli.connectWalletCheckPageViewed).toHaveBeenCalled() + expect(mockAmpli.connectWalletConnectPageViewed).toHaveBeenCalled() + expect(mockAmpli.connectWalletDetailsPageViewed).toHaveBeenCalled() + expect(mockAmpli.connectWalletDetailsSubmitted).toHaveBeenCalled() + + expect(mockAmpli.stakingCenterDelegationInitiated).toHaveBeenCalled() + expect(mockAmpli.stakingCenterDelegationSubmitted).toHaveBeenCalled() + + expect(mockAmpli.claimAdaTransactionInitiated).toHaveBeenCalled() + expect(mockAmpli.claimAdaTransactionSubmitted).toHaveBeenCalled() + + expect(mockAmpli.themeSelected).toHaveBeenCalledWith({theme: 'auto'}) + + expect(mockAmpli.dappPopupSignTransactionPageViewed).toHaveBeenCalled() + expect(mockAmpli.inAppNotificationOpened).toHaveBeenCalledWith({type: 'tx_received'}) expect(mockAmpli.inAppNotificationClosed).toHaveBeenCalledWith({type: 'tx_received'}) expect(mockAmpli.inAppNotificationViewed).toHaveBeenCalled() diff --git a/apps/wallet-mobile/src/kernel/metrics/metricsManager.tsx b/apps/wallet-mobile/src/kernel/metrics/metricsManager.tsx index 72f6a70b46..db07021b04 100644 --- a/apps/wallet-mobile/src/kernel/metrics/metricsManager.tsx +++ b/apps/wallet-mobile/src/kernel/metrics/metricsManager.tsx @@ -200,6 +200,24 @@ export const makeMetricsManager = ( inAppNotificationViewed: metricsModule.inAppNotificationViewed.bind(metricsModule), inAppNotificationClosed: metricsModule.inAppNotificationClosed.bind(metricsModule), settingsInAppNotificationsStatusUpdated: metricsModule.settingsInAppNotificationsStatusUpdated.bind(metricsModule), + + onboardingPinCodePageViewed: metricsModule.onboardingPinCodePageViewed.bind(metricsModule), + onboardingBiometricsPageViewed: metricsModule.onboardingBiometricsPageViewed.bind(metricsModule), + onboardingThemePageViewed: metricsModule.onboardingThemePageViewed.bind(metricsModule), + + connectWalletCheckPageViewed: metricsModule.connectWalletCheckPageViewed.bind(metricsModule), + connectWalletConnectPageViewed: metricsModule.connectWalletConnectPageViewed.bind(metricsModule), + connectWalletDetailsPageViewed: metricsModule.connectWalletDetailsPageViewed.bind(metricsModule), + connectWalletDetailsSubmitted: metricsModule.connectWalletDetailsSubmitted.bind(metricsModule), + + stakingCenterDelegationInitiated: metricsModule.stakingCenterDelegationInitiated.bind(metricsModule), + stakingCenterDelegationSubmitted: metricsModule.stakingCenterDelegationSubmitted.bind(metricsModule), + + claimAdaTransactionInitiated: metricsModule.claimAdaTransactionInitiated.bind(metricsModule), + claimAdaTransactionSubmitted: metricsModule.claimAdaTransactionSubmitted.bind(metricsModule), + + themeSelected: metricsModule.themeSelected.bind(metricsModule), + dappPopupSignTransactionPageViewed: metricsModule.dappPopupSignTransactionPageViewed.bind(metricsModule), } as const return { diff --git a/apps/wallet-mobile/src/kernel/metrics/mocks.ts b/apps/wallet-mobile/src/kernel/metrics/mocks.ts index 7005eaff2d..e9d3c22243 100644 --- a/apps/wallet-mobile/src/kernel/metrics/mocks.ts +++ b/apps/wallet-mobile/src/kernel/metrics/mocks.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */ +import {ClaimAdaTransactionSubmitted} from './ampli' import {MetricsManager} from './metricsManager' export const mockMetricsManager = (): MetricsManager => { @@ -108,6 +109,24 @@ export const mockMetricsManager = (): MetricsManager => { inAppNotificationClosed: e, inAppNotificationViewed: e, settingsInAppNotificationsStatusUpdated: e, + + onboardingPinCodePageViewed: e, + onboardingBiometricsPageViewed: e, + onboardingThemePageViewed: e, + + connectWalletCheckPageViewed: e, + connectWalletConnectPageViewed: e, + connectWalletDetailsPageViewed: e, + connectWalletDetailsSubmitted: e, + + stakingCenterDelegationInitiated: e, + stakingCenterDelegationSubmitted: e, + + claimAdaTransactionInitiated: e, + claimAdaTransactionSubmitted: e, + + themeSelected: e, + dappPopupSignTransactionPageViewed: e, } as const return { diff --git a/apps/wallet-mobile/src/legacy/Dashboard/Dashboard.tsx b/apps/wallet-mobile/src/legacy/Dashboard/Dashboard.tsx index d57b64ff8d..fca25a1f3c 100644 --- a/apps/wallet-mobile/src/legacy/Dashboard/Dashboard.tsx +++ b/apps/wallet-mobile/src/legacy/Dashboard/Dashboard.tsx @@ -29,6 +29,7 @@ import {WithdrawWarningModal} from '../../features/Staking/Governance/useCases/W import {useSelectedNetwork} from '../../features/WalletManager/common/hooks/useSelectedNetwork' import {useSelectedWallet} from '../../features/WalletManager/common/hooks/useSelectedWallet' import globalMessages from '../../kernel/i18n/global-messages' +import {useMetrics} from '../../kernel/metrics/metricsManager' import {DashboardRoutes, useWalletNavigation} from '../../kernel/navigation' import {isEmptyString} from '../../kernel/utils' import {useBalances, useIsOnline, useSync} from '../../yoroi-wallets/hooks' @@ -48,6 +49,7 @@ export const Dashboard = () => { const navigateTo = useNavigateTo() const governanceStrings = useStrings() const {isPoolRetiring} = usePoolTransition() + const {track} = useMetrics() const {wallet, meta} = useSelectedWallet() const {isLoading: isSyncing, sync} = useSync(wallet) @@ -68,6 +70,8 @@ export const Dashboard = () => { } const onWithdraw = () => { + track.claimAdaTransactionInitiated() + if (isGovernanceFeatureEnabled && !isParticipatingInGovernance) { openModal({ title: governanceStrings.withdrawWarningTitle, diff --git a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTx.tsx b/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTx.tsx deleted file mode 100644 index ad9128e703..0000000000 --- a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTx.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react' - -import {useSelectedWallet} from '../../../../features/WalletManager/common/hooks/useSelectedWallet' -import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types' -import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi' -import {ConfirmTxWithHW} from './ConfirmTxWithHW' -import {ConfirmTxWithOS} from './ConfirmTxWithOS' -import {ConfirmTxWithPassword} from './ConfirmTxWithPassword' - -type Props = { - wallet: YoroiWallet - unsignedTx: YoroiUnsignedTx - onCancel: () => void - onSuccess: () => void -} - -export const ConfirmTx = ({onSuccess, onCancel, unsignedTx}: Props) => { - const {meta, wallet} = useSelectedWallet() - return meta.isHW ? ( - - ) : meta.isEasyConfirmationEnabled ? ( - - ) : ( - - ) -} diff --git a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithHW.stories.tsx b/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithHW.stories.tsx deleted file mode 100644 index 01ebf062ee..0000000000 --- a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithHW.stories.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import {action} from '@storybook/addon-actions' -import {storiesOf} from '@storybook/react-native' -import React from 'react' - -import {WithModal} from '../../../../../.storybook/decorators' -import {Boundary} from '../../../../components/Boundary/Boundary' -import {mocks} from '../../../../yoroi-wallets/mocks/wallet' -import {ConfirmTxWithHW} from './ConfirmTxWithHW' - -storiesOf('ConfirmWithdrawalTx/HW', module) - .add('loading', () => ( - - - - - - )) - .add('error', () => ( - - - - - - )) - .add('withdrawals, no deregistrations', () => ( - - - - - - )) - .add('withdrawals, deregistrations', () => ( - - - - - - )) - .add('no withdrawals, deregistrations', () => ( - - - - - - )) diff --git a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithHW.tsx b/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithHW.tsx deleted file mode 100644 index a52eadb2e9..0000000000 --- a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithHW.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import {useTheme} from '@yoroi/theme' -import {App, HW} from '@yoroi/types' -import React from 'react' -import {useIntl} from 'react-intl' -import {StyleSheet, View} from 'react-native' - -import {Boundary} from '../../../../components/Boundary/Boundary' -import {TwoActionView} from '../../../../components/TwoActionView/TwoActionView' -import {useSelectedWallet} from '../../../../features/WalletManager/common/hooks/useSelectedWallet' -import {useWalletManager} from '../../../../features/WalletManager/context/WalletManagerProvider' -import {confirmationMessages, txLabels} from '../../../../kernel/i18n/global-messages' -import {throwLoggedError} from '../../../../kernel/logger/helpers/throw-logged-error' -import {useSignWithHwAndSubmitTx} from '../../../../yoroi-wallets/hooks' -import {withBLE, withUSB} from '../../../../yoroi-wallets/hw/hwWallet' -import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi' -import {LedgerConnect, LedgerTransportSwitch} from '../../../HW' -import {TransferSummary} from '../TransferSummary/TransferSummary' - -type Props = { - unsignedTx: YoroiUnsignedTx - onCancel: () => void - onSuccess: () => void -} - -type TransportType = 'USB' | 'BLE' - -export const ConfirmTxWithHW = (props: Props) => { - const {meta} = useSelectedWallet() - const {walletManager} = useWalletManager() - const [transportType, setTransportType] = React.useState('USB') - const [step, setStep] = React.useState<'select-transport' | 'connect-transport' | 'confirm'>('select-transport') - const {styles} = useStyles() - - const onSelectTransport = (transportType: TransportType) => { - setTransportType(transportType) - setStep('connect-transport') - } - - const onConnectBLE = (deviceId: string) => { - const hwDeviceInfo = withBLE(meta, deviceId) - walletManager.updateWalletHWDeviceInfo(meta.id, hwDeviceInfo) - setStep('confirm') - } - - const onConnectUSB = (deviceObj: HW.DeviceObj) => { - const hwDeviceInfo = withUSB(meta, deviceObj) - walletManager.updateWalletHWDeviceInfo(meta.id, hwDeviceInfo) - setStep('confirm') - } - - return ( - - - onSelectTransport('BLE')} - onSelectUSB={() => onSelectTransport('USB')} - /> - - - - - - - - - - - - - ) -} - -const Confirm = ({onSuccess, onCancel, unsignedTx, transport: transportType}: Props & {transport: TransportType}) => { - const strings = useStrings() - const {wallet, meta} = useSelectedWallet() - - const {signAndSubmitTx, isLoading} = useSignWithHwAndSubmitTx( - {wallet}, // - {signTx: {onSuccess}}, - ) - - const handleSignAndSubmitTx = () => { - if (meta.hwDeviceInfo == null) - throwLoggedError(new App.Errors.InvalidState('ConfirmTxWithHW: HW device info missing')) - - signAndSubmitTx({unsignedTx, useUSB: transportType === 'USB', hwDeviceInfo: meta.hwDeviceInfo}) - } - - return ( - onCancel(), - }} - > - - - ) -} - -const Route = ({active, children}: {active: boolean; children: React.ReactNode}) => <>{active ? children : null} - -const useStrings = () => { - const intl = useIntl() - - return { - confirmButton: intl.formatMessage(confirmationMessages.commonButtons.confirmButton), - confirmTx: intl.formatMessage(txLabels.confirmTx), - password: intl.formatMessage(txLabels.password), - } -} - -const useStyles = () => { - const {atoms} = useTheme() - const styles = StyleSheet.create({ - container: { - ...atoms.flex_1, - ...atoms.px_lg, - }, - }) - - return {styles} as const -} diff --git a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithOS.stories.tsx b/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithOS.stories.tsx deleted file mode 100644 index 16c017df62..0000000000 --- a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithOS.stories.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import {action} from '@storybook/addon-actions' -import {storiesOf} from '@storybook/react-native' -import React from 'react' - -import {WithModal} from '../../../../../.storybook/decorators' -import {Boundary} from '../../../../components/Boundary/Boundary' -import {mocks} from '../../../../yoroi-wallets/mocks/wallet' -import {ConfirmTxWithOS} from './ConfirmTxWithOS' - -storiesOf('ConfirmWithdrawalTx/OS', module) - .add('withdrawals, no deregistrations', () => ( - - - - - - )) - .add('withdrawals, deregistrations', () => ( - - - - - - )) - -const commonProps = { - onSuccess: action('onSuccess'), - onCancel: action('onCancel'), -} diff --git a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithOS.tsx b/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithOS.tsx deleted file mode 100644 index c80a99c387..0000000000 --- a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithOS.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import {useTheme} from '@yoroi/theme' -import React from 'react' -import {useIntl} from 'react-intl' -import {StyleSheet, View} from 'react-native' - -import {LoadingOverlay} from '../../../../components/LoadingOverlay/LoadingOverlay' -import {TwoActionView} from '../../../../components/TwoActionView/TwoActionView' -import {useAuthOsWithEasyConfirmation} from '../../../../features/Auth/common/hooks' -import {confirmationMessages, txLabels} from '../../../../kernel/i18n/global-messages' -import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types' -import {useSignAndSubmitTx} from '../../../../yoroi-wallets/hooks' -import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi' -import {TransferSummary} from '../TransferSummary/TransferSummary' - -type Props = { - wallet: YoroiWallet - unsignedTx: YoroiUnsignedTx - onCancel: () => void - onSuccess: () => void -} - -export const ConfirmTxWithOS = ({wallet, unsignedTx, onSuccess, onCancel}: Props) => { - const strings = useStrings() - const {styles} = useStyles() - - const {authWithOs, isLoading: authenticating} = useAuthOsWithEasyConfirmation( - {id: wallet.id}, - {onSuccess: (rootKey) => signAndSubmitTx({unsignedTx, rootKey})}, - ) - - const {signAndSubmitTx, isLoading: processingTx} = useSignAndSubmitTx( - {wallet}, - { - signTx: {useErrorBoundary: true}, - submitTx: {onSuccess, useErrorBoundary: true}, - }, - ) - - const isLoading = authenticating || processingTx - - return ( - - authWithOs(), - }} - secondaryButton={{ - disabled: isLoading, - onPress: () => onCancel(), - }} - > - - - - - - ) -} - -const useStrings = () => { - const intl = useIntl() - - return { - confirmButton: intl.formatMessage(confirmationMessages.commonButtons.confirmButton), - confirmTx: intl.formatMessage(txLabels.confirmTx), - } -} - -const useStyles = () => { - const {atoms} = useTheme() - const styles = StyleSheet.create({ - container: { - ...atoms.flex_1, - ...atoms.px_lg, - }, - }) - - return {styles} as const -} diff --git a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithPassword.stories.tsx b/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithPassword.stories.tsx deleted file mode 100644 index 28a8e9ddec..0000000000 --- a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithPassword.stories.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import {action} from '@storybook/addon-actions' -import {storiesOf} from '@storybook/react-native' -import React from 'react' - -import {WithModal} from '../../../../../.storybook/decorators' -import {Boundary} from '../../../../components/Boundary/Boundary' -import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types' -import {mocks} from '../../../../yoroi-wallets/mocks/wallet' -import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi' -import {ConfirmTxWithPassword} from './ConfirmTxWithPassword' - -storiesOf('ConfirmWithdrawalTx/Password', module) - .add('withdrawals, no deregistrations', () => { - const wallet: YoroiWallet = { - ...mocks.wallet, - signTx: mocks.signTx.success, - submitTransaction: mocks.submitTransaction.success, - } - const unsignedTx: YoroiUnsignedTx = { - ...mocks.yoroiUnsignedTx, - staking: { - ...mocks.yoroiUnsignedTx.staking, - withdrawals: [{address: 'withdrawal-address', amounts: {['.']: '12356789'}}], - }, - } - - return ( - - - - - - ) - }) - .add('withdrawals, deregistrations', () => { - const wallet: YoroiWallet = { - ...mocks.wallet, - signTx: mocks.signTx.success, - submitTransaction: mocks.submitTransaction.success, - } - const unsignedTx: YoroiUnsignedTx = { - ...mocks.yoroiUnsignedTx, - staking: { - ...mocks.yoroiUnsignedTx.staking, - deregistrations: [{address: 'deregistration-address', amounts: {['.']: '12356789'}}], - withdrawals: [{address: 'withdrawal-address', amounts: {['.']: '12356789'}}], - }, - } - - return ( - - - - - - ) - }) diff --git a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithPassword.tsx b/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithPassword.tsx deleted file mode 100644 index df67ab0bc0..0000000000 --- a/apps/wallet-mobile/src/legacy/Dashboard/WithdrawStakingRewards/ConfirmTx/ConfirmTxWithPassword.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import {useTheme} from '@yoroi/theme' -import React from 'react' -import {useIntl} from 'react-intl' -import {ActivityIndicator, StyleSheet, View} from 'react-native' -import {ScrollView} from 'react-native-gesture-handler' - -import {Button, ButtonType} from '../../../../components/Button/Button' -import {TextInput} from '../../../../components/TextInput/TextInput' -import {debugWalletInfo, features} from '../../../../kernel/features' -import {confirmationMessages, txLabels} from '../../../../kernel/i18n/global-messages' -import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types' -import {useSignWithPasswordAndSubmitTx} from '../../../../yoroi-wallets/hooks' -import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi' -import {TransferSummary} from '../TransferSummary/TransferSummary' - -type Props = { - wallet: YoroiWallet - unsignedTx: YoroiUnsignedTx - onCancel: () => void - onSuccess: () => void -} - -export const ConfirmTxWithPassword = ({wallet, onSuccess, onCancel, unsignedTx}: Props) => { - const strings = useStrings() - const {color} = useTheme() - const [password, setPassword] = React.useState(features.prefillWalletInfo ? debugWalletInfo.PASSWORD : '') - const intl = useIntl() - const {styles} = useStyles() - - const {signAndSubmitTx, isLoading} = useSignWithPasswordAndSubmitTx( - {wallet}, // - {submitTx: {onSuccess}}, - ) - - return ( - - - - - - - - -