Skip to content

Commit

Permalink
feat: STAKE-884 add more mobile pooled staking events (MetaMask#12651)
Browse files Browse the repository at this point in the history
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR adds more events related to the pooled-staking flows.

### Events Added

#### Stake Flow
- `Stake Cancel Clicked`
- `Stake Gas Cost Impact Warning Triggered`
- `Stake Gas Cost Impact Cancel Clicked`,
- `Stake Gas Cost Impact Proceeded Clicked`
- `Stake Confirmation Back Clicked`
- `Stake Transaction Initiated`
- `Stake Transaction Approved`
- `Stake Transaction Rejected`
- `Stake Transaction Confirmed`
- `Stake Transaction Failed`
- `Stake Transaction Submitted`

#### Unstake Flow
- `Unstake Cancel Clicked`
- `Unstake Confirmation Back Clicked`
- `Unstake Transaction Initiated`
- `Unstake Transaction Approved`
- `Unstake Transaction Rejected`
- `Unstake Transaction Confirmed`
- `Unstake Transaction Failed`
- `Unstake Transaction Submitted`

#### Misc
- `VISITED_ETH_OVERVIEW_WITH_STAKED_POSITIONS`

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Related issues**

Fixes: [STAKE-884: Add more mobile pooled staking
events](https://consensyssoftware.atlassian.net/browse/STAKE-884)

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
Matt561 authored Jan 9, 2025
1 parent 60667f7 commit 8cc7e0f
Show file tree
Hide file tree
Showing 21 changed files with 462 additions and 66 deletions.
42 changes: 36 additions & 6 deletions app/components/UI/Navbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import { toChecksumHexAddress } from '@metamask/controller-utils';
///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps)
import { isBtcAccount } from '../../../core/Multichain/utils';
///: END:ONLY_INCLUDE_IF
import { withMetaMetrics } from '../Stake/utils/metaMetrics/withMetaMetrics';

const trackEvent = (event, params = {}) => {
MetaMetrics.getInstance().trackEvent(event);
Expand Down Expand Up @@ -1949,16 +1950,23 @@ export const getSettingsNavigationOptions = (title, themeColors) => {
* @param {String} title - Navbar Title.
* @param {NavigationProp<ParamListBase>} navigation Navigation object returned from useNavigation hook.
* @param {ThemeColors} themeColors theme.colors returned from useStyles hook.
* @param {{ backgroundColor?: string, hasCancelButton?: boolean, hasBackButton?: boolean }} [options] - Optional options for navbar.
* @param {{ backgroundColor?: string, hasCancelButton?: boolean, hasBackButton?: boolean }} [navBarOptions] - Optional navbar options.
* @param {{ cancelButtonEvent?: { event: IMetaMetricsEvent, properties: Record<string, string> }, backButtonEvent?: { event: IMetaMetricsEvent, properties: Record<string, string>} }} [metricsOptions] - Optional metrics options.
* @returns Staking Navbar Component.
*/
export function getStakingNavbar(title, navigation, themeColors, options) {
const { hasBackButton = true, hasCancelButton = true } = options ?? {};
export function getStakingNavbar(
title,
navigation,
themeColors,
navBarOptions,
metricsOptions,
) {
const { hasBackButton = true, hasCancelButton = true } = navBarOptions ?? {};

const innerStyles = StyleSheet.create({
headerStyle: {
backgroundColor:
options?.backgroundColor ?? themeColors.background.default,
navBarOptions?.backgroundColor ?? themeColors.background.default,
shadowOffset: null,
},
headerLeft: {
Expand All @@ -1978,6 +1986,28 @@ export function getStakingNavbar(title, navigation, themeColors, options) {
navigation.goBack();
}

function handleBackPress() {
if (metricsOptions?.backButtonEvent) {
withMetaMetrics(navigationPop, {
event: metricsOptions.backButtonEvent.event,
properties: metricsOptions.backButtonEvent.properties,
});
} else {
navigationPop();
}
}

function handleCancelPress() {
if (metricsOptions?.cancelButtonEvent) {
withMetaMetrics(navigationPop, {
event: metricsOptions.cancelButtonEvent.event,
properties: metricsOptions.cancelButtonEvent.properties,
});
} else {
navigationPop();
}
}

return {
headerTitle: () => (
<View style={innerStyles.headerTitle}>
Expand All @@ -1990,7 +2020,7 @@ export function getStakingNavbar(title, navigation, themeColors, options) {
<ButtonIcon
size={ButtonIconSizes.Lg}
iconName={IconName.ArrowLeft}
onPress={navigationPop}
onPress={handleBackPress}
style={innerStyles.headerLeft}
/>
) : (
Expand All @@ -1999,7 +2029,7 @@ export function getStakingNavbar(title, navigation, themeColors, options) {
headerRight: () =>
hasCancelButton ? (
<TouchableOpacity
onPress={() => navigation.dangerouslyGetParent()?.pop()}
onPress={handleCancelPress}
style={styles.closeButton}
>
<Text style={innerStyles.headerButtonText}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { strings } from '../../../../../../locales/i18n';
import { FooterButtonGroupActions } from '../../components/StakingConfirmation/ConfirmationFooter/FooterButtonGroup/FooterButtonGroup.types';
import UnstakingTimeCard from '../../components/StakingConfirmation/UnstakeTimeCard/UnstakeTimeCard';
import { ScrollView } from 'react-native-gesture-handler';
import { MetaMetricsEvents } from '../../../../hooks/useMetrics';
import { EVENT_LOCATIONS, EVENT_PROVIDERS } from '../../constants/events';

const MOCK_STAKING_CONTRACT_NAME = 'MM Pooled Staking';

Expand All @@ -23,10 +25,24 @@ const StakeConfirmationView = ({ route }: StakeConfirmationViewProps) => {

useEffect(() => {
navigation.setOptions(
getStakingNavbar(strings('stake.stake'), navigation, theme.colors, {
backgroundColor: theme.colors.background.alternative,
hasCancelButton: false,
}),
getStakingNavbar(
strings('stake.stake'),
navigation,
theme.colors,
{
backgroundColor: theme.colors.background.alternative,
hasCancelButton: false,
},
{
backButtonEvent: {
event: MetaMetricsEvents.STAKE_CONFIRMATION_BACK_CLICKED,
properties: {
selected_provider: EVENT_PROVIDERS.CONSENSYS,
location: EVENT_LOCATIONS.STAKE_CONFIRMATION_VIEW,
},
},
},
),
);
}, [navigation, theme.colors]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ describe('StakeInputView', () => {
annualRewardRate: '2.5%',
annualRewardsETH: '0.00938 ETH',
annualRewardsFiat: '18.75 USD',
estimatedGasFee: '0.25',
estimatedGasFeePercentage: '66%',
},
});
});
Expand Down
57 changes: 47 additions & 10 deletions app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import useStakingInputHandlers from '../../hooks/useStakingInput';
import InputDisplay from '../../components/InputDisplay';
import { MetaMetricsEvents, useMetrics } from '../../../../hooks/useMetrics';
import { withMetaMetrics } from '../../utils/metaMetrics/withMetaMetrics';
import { formatEther } from 'ethers/lib/utils';
import { EVENT_PROVIDERS, EVENT_LOCATIONS } from '../../constants/events';

const StakeInputView = () => {
const title = strings('stake.stake_eth');
Expand Down Expand Up @@ -49,6 +51,8 @@ const StakeInputView = () => {
handleMax,
balanceValue,
isHighGasCostImpact,
getDepositTxGasPercentage,
estimatedGasFeeWei,
isLoadingStakingGasFee,
} = useStakingInputHandlers();

Expand All @@ -60,6 +64,21 @@ const StakeInputView = () => {

const handleStakePress = useCallback(() => {
if (isHighGasCostImpact()) {
trackEvent(
createEventBuilder(
MetaMetricsEvents.STAKE_GAS_COST_IMPACT_WARNING_TRIGGERED,
)
.addProperties({
selected_provider: EVENT_PROVIDERS.CONSENSYS,
location: EVENT_LOCATIONS.STAKE_INPUT_VIEW,
tokens_to_stake_native_value: amountEth,
tokens_to_stake_usd_value: fiatAmount,
estimated_gas_fee: formatEther(estimatedGasFeeWei.toString()),
estimated_gas_percentage_of_deposit: `${getDepositTxGasPercentage()}%`,
})
.build(),
);

navigation.navigate('StakeModals', {
screen: Routes.STAKING.MODALS.GAS_IMPACT,
params: {
Expand All @@ -68,6 +87,8 @@ const StakeInputView = () => {
annualRewardsETH,
annualRewardsFiat,
annualRewardRate,
estimatedGasFee: formatEther(estimatedGasFeeWei.toString()),
estimatedGasFeePercentage: `${getDepositTxGasPercentage()}%`,
},
});
return;
Expand All @@ -86,7 +107,7 @@ const StakeInputView = () => {
trackEvent(
createEventBuilder(MetaMetricsEvents.REVIEW_STAKE_BUTTON_CLICKED)
.addProperties({
selected_provider: 'consensys',
selected_provider: EVENT_PROVIDERS.CONSENSYS,
tokens_to_stake_native_value: amountEth,
tokens_to_stake_usd_value: fiatAmount,
})
Expand All @@ -103,6 +124,8 @@ const StakeInputView = () => {
trackEvent,
createEventBuilder,
amountEth,
estimatedGasFeeWei,
getDepositTxGasPercentage,
]);

const handleMaxButtonPress = () => {
Expand All @@ -124,9 +147,23 @@ const StakeInputView = () => {

useEffect(() => {
navigation.setOptions(
getStakingNavbar(title, navigation, theme.colors, {
hasBackButton: false,
}),
getStakingNavbar(
title,
navigation,
theme.colors,
{
hasBackButton: false,
},
{
cancelButtonEvent: {
event: MetaMetricsEvents.STAKE_CANCEL_CLICKED,
properties: {
selected_provider: EVENT_PROVIDERS.CONSENSYS,
location: EVENT_LOCATIONS.STAKE_INPUT_VIEW,
},
},
},
),
);
}, [navigation, theme.colors, title]);

Expand All @@ -148,9 +185,9 @@ const StakeInputView = () => {
handleCurrencySwitch={withMetaMetrics(handleCurrencySwitch, {
event: MetaMetricsEvents.STAKE_INPUT_CURRENCY_SWITCH_CLICKED,
properties: {
selected_provider: 'consensys',
selected_provider: EVENT_PROVIDERS.CONSENSYS,
text: 'Currency Switch Trigger',
location: 'Stake Input View',
location: EVENT_LOCATIONS.STAKE_INPUT_VIEW,
// We want to track the currency switching to. Not the current currency.
currency_type: isEth ? 'fiat' : 'native',
},
Expand All @@ -163,9 +200,9 @@ const StakeInputView = () => {
onIconPress={withMetaMetrics(navigateToLearnMoreModal, {
event: MetaMetricsEvents.TOOLTIP_OPENED,
properties: {
selected_provider: 'consensys',
selected_provider: EVENT_PROVIDERS.CONSENSYS,
text: 'Tooltip Opened',
location: 'Stake Input View',
location: EVENT_LOCATIONS.STAKE_INPUT_VIEW,
tooltip_name: 'MetaMask Pool Estimated Rewards',
},
})}
Expand All @@ -178,7 +215,7 @@ const StakeInputView = () => {
withMetaMetrics(handleQuickAmountPress, {
event: MetaMetricsEvents.STAKE_INPUT_QUICK_AMOUNT_CLICKED,
properties: {
location: 'StakeInputView',
location: EVENT_LOCATIONS.STAKE_INPUT_VIEW,
amount: value,
// onMaxPress is called instead when it's defined and the max is clicked.
is_max: false,
Expand All @@ -189,7 +226,7 @@ const StakeInputView = () => {
onMaxPress={withMetaMetrics(handleMaxButtonPress, {
event: MetaMetricsEvents.STAKE_INPUT_QUICK_AMOUNT_CLICKED,
properties: {
location: 'StakeInputView',
location: EVENT_LOCATIONS.STAKE_INPUT_VIEW,
is_max: true,
mode: isEth ? 'native' : 'fiat',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import TokenValueStack from '../../components/StakingConfirmation/TokenValueStac
import AccountCard from '../../components/StakingConfirmation/AccountCard/AccountCard';
import ConfirmationFooter from '../../components/StakingConfirmation/ConfirmationFooter/ConfirmationFooter';
import { FooterButtonGroupActions } from '../../components/StakingConfirmation/ConfirmationFooter/FooterButtonGroup/FooterButtonGroup.types';
import { MetaMetricsEvents } from '../../../../hooks/useMetrics';
import { EVENT_LOCATIONS, EVENT_PROVIDERS } from '../../constants/events';

const MOCK_STAKING_CONTRACT_NAME = 'MM Pooled Staking';

Expand All @@ -21,10 +23,24 @@ const UnstakeConfirmationView = ({ route }: UnstakeConfirmationViewProps) => {

useEffect(() => {
navigation.setOptions(
getStakingNavbar(strings('stake.unstake'), navigation, theme.colors, {
backgroundColor: theme.colors.background.alternative,
hasCancelButton: false,
}),
getStakingNavbar(
strings('stake.unstake'),
navigation,
theme.colors,
{
backgroundColor: theme.colors.background.alternative,
hasCancelButton: false,
},
{
backButtonEvent: {
event: MetaMetricsEvents.UNSTAKE_CONFIRMATION_BACK_CLICKED,
properties: {
selected_provider: EVENT_PROVIDERS.CONSENSYS,
location: EVENT_LOCATIONS.UNSTAKE_CONFIRMATION_VIEW,
},
},
},
),
);
}, [navigation, theme.colors]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Routes from '../../../../../constants/navigation/Routes';
import { MetaMetricsEvents, useMetrics } from '../../../../hooks/useMetrics';
import useUnstakingInputHandlers from '../../hooks/useUnstakingInput';
import { withMetaMetrics } from '../../utils/metaMetrics/withMetaMetrics';
import { EVENT_LOCATIONS, EVENT_PROVIDERS } from '../../constants/events';

const UnstakeInputView = () => {
const title = strings('stake.unstake_eth');
Expand Down Expand Up @@ -54,9 +55,23 @@ const UnstakeInputView = () => {

useEffect(() => {
navigation.setOptions(
getStakingNavbar(title, navigation, theme.colors, {
hasBackButton: false,
}),
getStakingNavbar(
title,
navigation,
theme.colors,
{
hasBackButton: false,
},
{
cancelButtonEvent: {
event: MetaMetricsEvents.UNSTAKE_CANCEL_CLICKED,
properties: {
selected_provider: EVENT_PROVIDERS.CONSENSYS,
location: EVENT_LOCATIONS.UNSTAKE_INPUT_VIEW,
},
},
},
),
);
}, [navigation, theme.colors, title]);

Expand All @@ -71,7 +86,7 @@ const UnstakeInputView = () => {
trackEvent(
createEventBuilder(MetaMetricsEvents.REVIEW_UNSTAKE_BUTTON_CLICKED)
.addProperties({
selected_provider: 'consensys',
selected_provider: EVENT_PROVIDERS.CONSENSYS,
tokens_to_stake_native_value: amountEth,
tokens_to_stake_usd_value: fiatAmount,
})
Expand Down Expand Up @@ -100,9 +115,9 @@ const UnstakeInputView = () => {
handleCurrencySwitch={withMetaMetrics(handleCurrencySwitch, {
event: MetaMetricsEvents.UNSTAKE_INPUT_CURRENCY_SWITCH_CLICKED,
properties: {
selected_provider: 'consensys',
selected_provider: EVENT_PROVIDERS.CONSENSYS,
text: 'Currency Switch Trigger',
location: 'Unstake Input View',
location: EVENT_LOCATIONS.UNSTAKE_INPUT_VIEW,
// We want to track the currency switching to. Not the current currency.
currency_type: isEth ? 'fiat' : 'native',
},
Expand All @@ -116,7 +131,7 @@ const UnstakeInputView = () => {
withMetaMetrics(handleQuickAmountPress, {
event: MetaMetricsEvents.UNSTAKE_INPUT_QUICK_AMOUNT_CLICKED,
properties: {
location: 'UnstakeInputView',
location: EVENT_LOCATIONS.UNSTAKE_INPUT_VIEW,
amount: value,
is_max: value === 1,
mode: isEth ? 'native' : 'fiat',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const props: GasImpactModalProps = {
annualRewardRate: '2.5%',
annualRewardsETH: '2.5 ETH',
annualRewardsFiat: '$5000',
estimatedGasFee: '0.009171428571428572',
estimatedGasFeePercentage: '35%',
},
name: 'params',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ interface GasImpactModalRouteParams {
annualRewardsETH: string;
annualRewardsFiat: string;
annualRewardRate: string;
estimatedGasFee: string;
estimatedGasFeePercentage: string;
}

export interface GasImpactModalProps {
Expand Down
Loading

0 comments on commit 8cc7e0f

Please sign in to comment.