From 7b9bd028a35dd79944f1f449501028bc2d041d79 Mon Sep 17 00:00:00 2001
From: Matthew Grainger <46547583+Matt561@users.noreply.github.com>
Date: Thu, 14 Nov 2024 16:15:35 -0500
Subject: [PATCH] feat: STAKE-827: track additional pooled staking events
(#12290)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Adds additional event tracking for pooled-staking tooltips and currency
switching.
## **Related issues**
Jira Ticket: [STAKE-827: Track more events in
Mixpanel](https://consensyssoftware.atlassian.net/browse/STAKE-827)
## **Manual testing steps**
**note: there's an ongoing issues with tracking events on local dev.
Results may vary.**
Prerequisite: Add `export MM_POOLED_STAKING_UI_ENABLED=true` to your
local `.js.env` file
Testing Currency Switch Events
1. Click on Ethereum in assets list
2. Click "Stake", "Stake More", or "Unstake" buttons to navigate to the
input screen
3. Switch the currency between native and fiat near the top of the
screen
Testing Tooltip Events
1. Click on Ethereum in assets list
2. Click on available tooltip icons:
- Annual rate in the "Your earnings" section within ETH details page
- Learn more tooltip on the staking input screen
- Various tooltips on the stake and unstake confirmation views
## **Screenshots/Recordings**
N/A
## **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
- [x] 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.
---
.../KeyValueLabel/KeyValueLabel.tsx | 1 +
.../KeyValueRow/KeyValueRow.types.ts | 4 ++
.../Views/StakeInputView/StakeInputView.tsx | 31 ++++++----
.../StakeInputView.test.tsx.snap | 2 +-
.../UnstakeInputView/UnstakeInputView.tsx | 33 ++++++++---
.../components/EstimatedAnnualRewardsCard.tsx | 2 +-
.../Stake/components/LearnMoreModal/index.tsx | 39 ++++++-------
.../RewardsCard/RewardsCard.tsx | 12 ++++
.../UnstakeTimeCard/UnstakeTimeCard.tsx | 11 ++++
.../components/StakingEarnings/index.tsx | 13 ++++-
.../metaMetrics/tooltipMetaMetricsUtils.ts | 23 ++++++++
.../utils/metaMetrics/withMetaMetrics.ts | 56 +++++++++++++++++++
app/core/Analytics/MetaMetrics.events.ts | 34 +++++++++--
13 files changed, 213 insertions(+), 48 deletions(-)
create mode 100644 app/components/UI/Stake/utils/metaMetrics/tooltipMetaMetricsUtils.ts
create mode 100644 app/components/UI/Stake/utils/metaMetrics/withMetaMetrics.ts
diff --git a/app/component-library/components-temp/KeyValueRow/KeyValueLabel/KeyValueLabel.tsx b/app/component-library/components-temp/KeyValueRow/KeyValueLabel/KeyValueLabel.tsx
index bfc064931ee..748463f59a0 100644
--- a/app/component-library/components-temp/KeyValueRow/KeyValueLabel/KeyValueLabel.tsx
+++ b/app/component-library/components-temp/KeyValueRow/KeyValueLabel/KeyValueLabel.tsx
@@ -35,6 +35,7 @@ const KeyValueRowLabel = ({ label, tooltip }: KeyValueRowLabelProps) => {
const onNavigateToTooltipModal = () => {
if (!hasTooltip) return;
openTooltipModal(tooltip.title, tooltip.content);
+ tooltip?.onPress?.();
};
return (
diff --git a/app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts b/app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts
index fc4e825921e..b04e893bd62 100644
--- a/app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts
+++ b/app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts
@@ -27,6 +27,10 @@ interface KeyValueRowTooltip {
* @default TooltipSizes.Md
*/
size?: ButtonIconSizes;
+ /**
+ * Optional onPress handler
+ */
+ onPress?: (...args: unknown[]) => unknown;
}
/**
diff --git a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
index 9c5e09462fa..56c3cc749ae 100644
--- a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
+++ b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
@@ -19,6 +19,7 @@ import styleSheet from './StakeInputView.styles';
import useStakingInputHandlers from '../../hooks/useStakingInput';
import InputDisplay from '../../components/InputDisplay';
import { MetaMetricsEvents, useMetrics } from '../../../../hooks/useMetrics';
+import { withMetaMetrics } from '../../utils/metaMetrics/withMetaMetrics';
const StakeInputView = () => {
const title = strings('stake.stake_eth');
@@ -55,15 +56,6 @@ const StakeInputView = () => {
navigation.navigate('StakeModals', {
screen: Routes.STAKING.MODALS.LEARN_MORE,
});
- trackEvent(
- createEventBuilder(MetaMetricsEvents.STAKE_LEARN_MORE_CLICKED)
- .addProperties({
- selected_provider: 'consensys',
- text: 'Tooltip Question Mark Trigger',
- location: 'Stake Input View',
- })
- .build(),
- );
};
const handleStakePress = useCallback(() => {
@@ -153,13 +145,30 @@ const StakeInputView = () => {
fiatAmount={fiatAmount}
isEth={isEth}
currentCurrency={currentCurrency}
- handleCurrencySwitch={handleCurrencySwitch}
+ handleCurrencySwitch={withMetaMetrics(handleCurrencySwitch, {
+ event: MetaMetricsEvents.STAKE_INPUT_CURRENCY_SWITCH_CLICKED,
+ properties: {
+ selected_provider: 'consensys',
+ text: 'Currency Switch Trigger',
+ location: 'Stake Input View',
+ // We want to track the currency switching to. Not the current currency.
+ currency_type: isEth ? 'fiat' : 'native',
+ },
+ })}
currencyToggleValue={currencyToggleValue}
/>
diff --git a/app/components/UI/Stake/Views/StakeInputView/__snapshots__/StakeInputView.test.tsx.snap b/app/components/UI/Stake/Views/StakeInputView/__snapshots__/StakeInputView.test.tsx.snap
index 0193ba5abe1..fb47e1bf1c1 100644
--- a/app/components/UI/Stake/Views/StakeInputView/__snapshots__/StakeInputView.test.tsx.snap
+++ b/app/components/UI/Stake/Views/StakeInputView/__snapshots__/StakeInputView.test.tsx.snap
@@ -567,7 +567,7 @@ exports[`StakeInputView render matches snapshot 1`] = `
onPress={[Function]}
>
{
const title = strings('stake.unstake_eth');
@@ -68,14 +69,21 @@ const UnstakeInputView = () => {
});
trackEvent(
createEventBuilder(MetaMetricsEvents.REVIEW_UNSTAKE_BUTTON_CLICKED)
- .addProperties({
- selected_provider: 'consensys',
- tokens_to_stake_native_value: amountEth,
- tokens_to_stake_usd_value: fiatAmount,
- })
- .build(),
+ .addProperties({
+ selected_provider: 'consensys',
+ tokens_to_stake_native_value: amountEth,
+ tokens_to_stake_usd_value: fiatAmount,
+ })
+ .build(),
);
- }, [amountEth, amountWei, createEventBuilder, fiatAmount, navigation, trackEvent]);
+ }, [
+ amountEth,
+ amountWei,
+ createEventBuilder,
+ fiatAmount,
+ navigation,
+ trackEvent,
+ ]);
return (
@@ -88,7 +96,16 @@ const UnstakeInputView = () => {
fiatAmount={fiatAmount}
isEth={isEth}
currentCurrency={currentCurrency}
- handleCurrencySwitch={handleCurrencySwitch}
+ handleCurrencySwitch={withMetaMetrics(handleCurrencySwitch, {
+ event: MetaMetricsEvents.UNSTAKE_INPUT_CURRENCY_SWITCH_CLICKED,
+ properties: {
+ selected_provider: 'consensys',
+ text: 'Currency Switch Trigger',
+ location: 'Unstake Input View',
+ // We want to track the currency switching to. Not the current currency.
+ currency_type: isEth ? 'fiat' : 'native',
+ },
+ })}
currencyToggleValue={currencyToggleValue}
/>
diff --git a/app/components/UI/Stake/components/EstimatedAnnualRewardsCard.tsx b/app/components/UI/Stake/components/EstimatedAnnualRewardsCard.tsx
index 7c2b306cef3..92cc7b63ba3 100644
--- a/app/components/UI/Stake/components/EstimatedAnnualRewardsCard.tsx
+++ b/app/components/UI/Stake/components/EstimatedAnnualRewardsCard.tsx
@@ -69,7 +69,7 @@ const EstimatedAnnualRewardsCard = ({
>
diff --git a/app/components/UI/Stake/components/LearnMoreModal/index.tsx b/app/components/UI/Stake/components/LearnMoreModal/index.tsx
index b33f5aeba49..eb321f8d238 100644
--- a/app/components/UI/Stake/components/LearnMoreModal/index.tsx
+++ b/app/components/UI/Stake/components/LearnMoreModal/index.tsx
@@ -17,7 +17,8 @@ import { useNavigation } from '@react-navigation/native';
import { strings } from '../../../../../../locales/i18n';
import { POOLED_STAKING_FAQ_URL } from '../../constants';
import createLearnMoreModalStyles from './LearnMoreModal.styles';
-import { MetaMetricsEvents, useMetrics } from '../../../../hooks/useMetrics';
+import { MetaMetricsEvents } from '../../../../hooks/useMetrics';
+import { withMetaMetrics } from '../../utils/metaMetrics/withMetaMetrics';
const styles = createLearnMoreModalStyles();
@@ -42,12 +43,21 @@ const LearnMoreModal = () => {
const sheetRef = useRef(null);
const navigation = useNavigation();
- const { trackEvent, createEventBuilder } = useMetrics();
const handleClose = () => {
sheetRef.current?.onCloseBottomSheet();
};
+ const handleLearnMoreBrowserRedirect = () => {
+ // Take to the faq page
+ navigation.navigate('Webview', {
+ screen: 'SimpleWebview',
+ params: {
+ url: POOLED_STAKING_FAQ_URL,
+ },
+ });
+ };
+
return (
@@ -86,23 +96,14 @@ const LearnMoreModal = () => {
{isLoadingEarningsData ? (
diff --git a/app/components/UI/Stake/utils/metaMetrics/tooltipMetaMetricsUtils.ts b/app/components/UI/Stake/utils/metaMetrics/tooltipMetaMetricsUtils.ts
new file mode 100644
index 00000000000..e28a9431c92
--- /dev/null
+++ b/app/components/UI/Stake/utils/metaMetrics/tooltipMetaMetricsUtils.ts
@@ -0,0 +1,23 @@
+import { MetricsEventBuilder } from '../../../../../core/Analytics/MetricsEventBuilder';
+import { MetaMetricsEvents } from '../../../../hooks/useMetrics';
+
+export const getTooltipMetricProperties = (
+ location: string,
+ tooltipName: string,
+) => ({
+ selected_provider: 'consensys',
+ text: 'Tooltip Opened',
+ location,
+ tooltip_name: tooltipName,
+});
+
+export const createTooltipOpenedEvent = (
+ location: string,
+ tooltipName: string,
+) => {
+ const createEventBuilder = MetricsEventBuilder.createEventBuilder;
+
+ return createEventBuilder(MetaMetricsEvents.TOOLTIP_OPENED)
+ .addProperties(getTooltipMetricProperties(location, tooltipName))
+ .build();
+};
diff --git a/app/components/UI/Stake/utils/metaMetrics/withMetaMetrics.ts b/app/components/UI/Stake/utils/metaMetrics/withMetaMetrics.ts
new file mode 100644
index 00000000000..ba828b96577
--- /dev/null
+++ b/app/components/UI/Stake/utils/metaMetrics/withMetaMetrics.ts
@@ -0,0 +1,56 @@
+import {
+ IMetaMetricsEvent,
+ JsonMap,
+} from '../../../../../core/Analytics/MetaMetrics.types';
+import { MetricsEventBuilder } from '../../../../../core/Analytics/MetricsEventBuilder';
+import { MetaMetrics } from '../../../../../core/Analytics';
+
+interface WithMetaMetricsEvent {
+ event: IMetaMetricsEvent;
+ properties?: JsonMap;
+}
+
+const createEventBuilder = MetricsEventBuilder.createEventBuilder;
+
+const shouldAddProperties = (properties?: JsonMap): properties is JsonMap => {
+ if (!properties) return false;
+ return Object.keys(properties).length > 0;
+};
+
+const buildEvent = (e: WithMetaMetricsEvent) => {
+ const eventBuilder = createEventBuilder(e.event);
+
+ if (shouldAddProperties(e?.properties)) {
+ eventBuilder.addProperties(e.properties);
+ }
+
+ return eventBuilder.build();
+};
+
+export const withMetaMetrics = unknown>(
+ func: T,
+ events: WithMetaMetricsEvent | WithMetaMetricsEvent[],
+) => {
+ if (!Array.isArray(events)) {
+ events = [events];
+ }
+
+ const builtEvents = events.map((event) => buildEvent(event));
+
+ return (...args: Parameters): ReturnType | Promise> => {
+ const result = func(...args);
+
+ if (result instanceof Promise) {
+ return result.then((res) => {
+ builtEvents.forEach((event) =>
+ MetaMetrics.getInstance().trackEvent(event),
+ );
+ return res;
+ }) as Promise>;
+ }
+
+ builtEvents.forEach((event) => MetaMetrics.getInstance().trackEvent(event));
+
+ return result as ReturnType;
+ };
+};
diff --git a/app/core/Analytics/MetaMetrics.events.ts b/app/core/Analytics/MetaMetrics.events.ts
index 93d279590b0..1925896b1fc 100644
--- a/app/core/Analytics/MetaMetrics.events.ts
+++ b/app/core/Analytics/MetaMetrics.events.ts
@@ -281,6 +281,8 @@ enum EVENT_NAME {
STAKE_WITHDRAW_BUTTON_CLICKED = 'Stake Withdraw Button Clicked',
STAKE_CLAIM_BUTTON_CLICKED = 'Stake Claim Button Clicked',
STAKE_LEARN_MORE_CLICKED = 'Stake Learn More Clicked',
+ STAKE_INPUT_CURRENCY_SWITCH_CLICKED = 'Stake Input Currency Switch Clicked',
+ UNSTAKE_INPUT_CURRENCY_SWITCH_CLICKED = 'Unstake Input Currency Switch Clicked',
// Force Upgrade | Automatic Security Checks
FORCE_UPGRADE_UPDATE_NEEDED_PROMPT_VIEWED = 'Force Upgrade Update Needed Prompt Viewed',
@@ -389,6 +391,9 @@ enum EVENT_NAME {
// Connection
CONNECTION_DROPPED = 'Connection dropped',
CONNECTION_RESTORED = 'Connection restored',
+
+ // Tooltip
+ TOOLTIP_OPENED = 'Tooltip Opened',
}
enum ACTIONS {
@@ -554,6 +559,7 @@ const events = {
BROWSER_RELOAD: generateOpt(EVENT_NAME.BROWSER_RELOAD),
BROWSER_ADD_FAVORITES: generateOpt(EVENT_NAME.BROWSER_ADD_FAVORITES),
DAPP_VIEWED: generateOpt(EVENT_NAME.DAPP_VIEWED),
+ TOOLTIP_OPENED: generateOpt(EVENT_NAME.TOOLTIP_OPENED),
// Security & Privacy Settings
VIEW_SECURITY_SETTINGS: generateOpt(EVENT_NAME.VIEW_SECURITY_SETTINGS),
BASIC_FUNCTIONALITY_ENABLED: generateOpt(
@@ -884,12 +890,28 @@ const events = {
CONNECTION_RESTORED: generateOpt(EVENT_NAME.CONNECTION_RESTORED),
// Stake
- REVIEW_STAKE_BUTTON_CLICKED: generateOpt(EVENT_NAME.REVIEW_STAKE_BUTTON_CLICKED),
- REVIEW_UNSTAKE_BUTTON_CLICKED: generateOpt(EVENT_NAME.REVIEW_UNSTAKE_BUTTON_CLICKED),
- STAKE_INPUT_AMOUNT_CLICKED: generateOpt(EVENT_NAME.STAKE_INPUT_AMOUNT_CLICKED),
- STAKE_WITHDRAW_BUTTON_CLICKED: generateOpt(EVENT_NAME.STAKE_WITHDRAW_BUTTON_CLICKED),
- STAKE_CLAIM_BUTTON_CLICKED: generateOpt(EVENT_NAME.STAKE_CLAIM_BUTTON_CLICKED),
- STAKE_LEARN_MORE_CLICKED: generateOpt(EVENT_NAME.STAKE_LEARN_MORE_CLICKED)
+ REVIEW_STAKE_BUTTON_CLICKED: generateOpt(
+ EVENT_NAME.REVIEW_STAKE_BUTTON_CLICKED,
+ ),
+ REVIEW_UNSTAKE_BUTTON_CLICKED: generateOpt(
+ EVENT_NAME.REVIEW_UNSTAKE_BUTTON_CLICKED,
+ ),
+ STAKE_INPUT_AMOUNT_CLICKED: generateOpt(
+ EVENT_NAME.STAKE_INPUT_AMOUNT_CLICKED,
+ ),
+ STAKE_WITHDRAW_BUTTON_CLICKED: generateOpt(
+ EVENT_NAME.STAKE_WITHDRAW_BUTTON_CLICKED,
+ ),
+ STAKE_CLAIM_BUTTON_CLICKED: generateOpt(
+ EVENT_NAME.STAKE_CLAIM_BUTTON_CLICKED,
+ ),
+ STAKE_LEARN_MORE_CLICKED: generateOpt(EVENT_NAME.STAKE_LEARN_MORE_CLICKED),
+ STAKE_INPUT_CURRENCY_SWITCH_CLICKED: generateOpt(
+ EVENT_NAME.STAKE_INPUT_CURRENCY_SWITCH_CLICKED,
+ ),
+ UNSTAKE_INPUT_CURRENCY_SWITCH_CLICKED: generateOpt(
+ EVENT_NAME.UNSTAKE_INPUT_CURRENCY_SWITCH_CLICKED,
+ ),
};
/**