Skip to content

Commit

Permalink
feat: updated staking events to use withMetaMetrics helper (#12337)
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 updates the events added in #12144 to use the `withMetaMetrics`
helper function.
<!--
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**

Jira Ticket: [STAKE-876: Wrap existing Staking events with
withMetaMetrics
hook](https://consensyssoftware.atlassian.net/browse/STAKE-876)

## **Manual testing steps**

Prerequisite: Add `export MM_POOLED_STAKING_UI_ENABLED=true` to your
local `.js.env` file.

All events can be tested by running through the stake and unstake flows.

## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->
N/A
### **After**

<!-- [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
- [x] 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 Nov 26, 2024
1 parent 39536b5 commit 4a2b689
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 63 deletions.
24 changes: 21 additions & 3 deletions app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const StakeInputView = () => {
handleCurrencySwitch,
currencyToggleValue,
percentageOptions,
handleAmountPress,
handleQuickAmountPress,
handleKeypadChange,
calculateEstimatedAnnualRewards,
estimatedAnnualRewards,
Expand Down Expand Up @@ -174,8 +174,26 @@ const StakeInputView = () => {
</View>
<QuickAmounts
amounts={percentageOptions}
onAmountPress={handleAmountPress}
onMaxPress={handleMaxButtonPress}
onAmountPress={({ value }: { value: number }) =>
withMetaMetrics(handleQuickAmountPress, {
event: MetaMetricsEvents.STAKE_INPUT_QUICK_AMOUNT_CLICKED,
properties: {
location: 'StakeInputView',
amount: value,
// onMaxPress is called instead when it's defined and the max is clicked.
is_max: false,
mode: isEth ? 'native' : 'fiat',
},
})({ value })
}
onMaxPress={withMetaMetrics(handleMaxButtonPress, {
event: MetaMetricsEvents.STAKE_INPUT_QUICK_AMOUNT_CLICKED,
properties: {
location: 'StakeInputView',
is_max: true,
mode: isEth ? 'native' : 'fiat',
},
})}
/>
<Keypad
value={isEth ? amountEth : fiatAmount}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const UnstakeInputView = () => {
const title = strings('stake.unstake_eth');
const navigation = useNavigation();
const { styles, theme } = useStyles(styleSheet, {});

const { trackEvent, createEventBuilder } = useMetrics();

const {
Expand All @@ -38,7 +39,7 @@ const UnstakeInputView = () => {
handleCurrencySwitch,
currencyToggleValue,
percentageOptions,
handleAmountPress,
handleQuickAmountPress,
handleKeypadChange,
stakedBalanceValue,
} = useUnstakingInputHandlers();
Expand Down Expand Up @@ -111,7 +112,17 @@ const UnstakeInputView = () => {
<UnstakeInputViewBanner style={styles.unstakeBanner} />
<QuickAmounts
amounts={percentageOptions}
onAmountPress={handleAmountPress}
onAmountPress={({ value }: { value: number }) =>
withMetaMetrics(handleQuickAmountPress, {
event: MetaMetricsEvents.UNSTAKE_INPUT_QUICK_AMOUNT_CLICKED,
properties: {
location: 'UnstakeInputView',
amount: value,
is_max: value === 1,
mode: isEth ? 'native' : 'fiat',
},
})({ value })
}
/>
<Keypad
value={isEth ? amountEth : fiatAmount}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ import { useSelector } from 'react-redux';
import { selectSelectedInternalAccount } from '../../../../../../../selectors/accountsController';
import usePooledStakes from '../../../../hooks/usePooledStakes';
import Engine from '../../../../../../../core/Engine';
import { MetaMetricsEvents, useMetrics } from '../../../../../../hooks/useMetrics';
import {
MetaMetricsEvents,
useMetrics,
} from '../../../../../../hooks/useMetrics';

type StakeBannerProps = Pick<BannerProps, 'style'> & {
claimableAmount: string;
};

const ClaimBanner = ({ claimableAmount, style }: StakeBannerProps) => {
const { styles } = useStyles(styleSheet, {});

const { trackEvent, createEventBuilder } = useMetrics();

const [isSubmittingClaimTransaction, setIsSubmittingClaimTransaction] =
useState(false);

Expand All @@ -44,10 +47,10 @@ const ClaimBanner = ({ claimableAmount, style }: StakeBannerProps) => {

trackEvent(
createEventBuilder(MetaMetricsEvents.STAKE_CLAIM_BUTTON_CLICKED)
.addProperties({
location: 'Token Details'
})
.build()
.addProperties({
location: 'Token Details',
})
.build(),
);

setIsSubmittingClaimTransaction(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,27 @@ const StakingButtons = ({
});
trackEvent(
createEventBuilder(MetaMetricsEvents.STAKE_WITHDRAW_BUTTON_CLICKED)
.addProperties({
location: 'Token Details',
text: 'Unstake',
token_symbol: 'ETH',
chain_id: chainId,
})
.build()
.addProperties({
location: 'Token Details',
text: 'Unstake',
token_symbol: 'ETH',
chain_id: chainId,
})
.build(),
);
};

const onStakePress = () => {
navigate('StakeScreens', { screen: Routes.STAKING.STAKE });
trackEvent(
createEventBuilder(MetaMetricsEvents.STAKE_BUTTON_CLICKED)
.addProperties({
location: 'Token Details',
text: 'Stake',
token_symbol: 'ETH',
chain_id: chainId,
})
.build()
.addProperties({
location: 'Token Details',
text: 'Stake',
token_symbol: 'ETH',
chain_id: chainId,
})
.build(),
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@ import Button, {
import { strings } from '../../../../../../../locales/i18n';
import { useNavigation } from '@react-navigation/native';
import Routes from '../../../../../../constants/navigation/Routes';
import { useMetrics, MetaMetricsEvents } from '../../../../../hooks/useMetrics';
import { MetaMetricsEvents, useMetrics } from '../../../../../hooks/useMetrics';

interface StakingCtaProps extends Pick<ViewProps, 'style'> {
estimatedRewardRate: string;
}

const StakingCta = ({ estimatedRewardRate, style }: StakingCtaProps) => {
const { styles } = useStyles(styleSheet, {});
const { trackEvent, createEventBuilder } = useMetrics();

const { navigate } = useNavigation();
const { trackEvent, createEventBuilder } = useMetrics();

const navigateToLearnMoreModal = () => {
navigate('StakeModals', {
Expand Down
31 changes: 4 additions & 27 deletions app/components/UI/Stake/hooks/useInputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
fromWei,
} from '../../../../util/number';
import { strings } from '../../../../../locales/i18n';
import { useMetrics, MetaMetricsEvents } from '../../../hooks/useMetrics';

interface InputHandlerParams {
balance: BN;
Expand All @@ -28,8 +27,6 @@ const useInputHandler = ({ balance }: InputHandlerParams) => {
const currentCurrency = useSelector(selectCurrentCurrency);
const conversionRate = useSelector(selectConversionRate) || 1;

const { trackEvent, createEventBuilder } = useMetrics();

const isNonZeroAmount = useMemo(() => amountWei.gt(new BN(0)), [amountWei]);

const isOverMaximum = useMemo(
Expand Down Expand Up @@ -97,7 +94,7 @@ const useInputHandler = ({ balance }: InputHandlerParams) => {
{ value: 1, label: strings('stake.max') },
];

const handleAmountPress = useCallback(
const handleQuickAmountPress = useCallback(
({ value }: { value: number }) => {
const percentage = value * 100;
const amountPercentage = balance.mul(new BN(percentage)).div(new BN(100));
Expand All @@ -117,18 +114,8 @@ const useInputHandler = ({ balance }: InputHandlerParams) => {
2,
).toString();
setFiatAmount(newFiatAmount);
trackEvent(
createEventBuilder(MetaMetricsEvents.STAKE_INPUT_AMOUNT_CLICKED)
.addProperties({
location: 'Stake',
amount: value,
is_max: value === 1,
mode: isEth ? 'native' : 'fiat',
})
.build(),
);
},
[balance, conversionRate, createEventBuilder, isEth, trackEvent],
[balance, conversionRate],
);

const handleMaxInput = useCallback(
Expand All @@ -149,18 +136,8 @@ const useInputHandler = ({ balance }: InputHandlerParams) => {
2,
).toString();
setFiatAmount(fiatValue);
trackEvent(
createEventBuilder(MetaMetricsEvents.STAKE_INPUT_AMOUNT_CLICKED)
.addProperties({
location: 'Stake',
amount: ethValue,
is_max: true,
mode: isEth ? 'native' : 'fiat',
})
.build(),
);
},
[conversionRate, createEventBuilder, isEth, trackEvent],
[conversionRate],
);

const currencyToggleValue = isEth
Expand All @@ -180,7 +157,7 @@ const useInputHandler = ({ balance }: InputHandlerParams) => {
handleKeypadChange,
handleCurrencySwitch,
percentageOptions,
handleAmountPress,
handleQuickAmountPress,
currentCurrency,
conversionRate,
handleMaxInput,
Expand Down
4 changes: 2 additions & 2 deletions app/components/UI/Stake/hooks/useStakingInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const useStakingInputHandlers = () => {
handleKeypadChange,
handleCurrencySwitch,
percentageOptions,
handleAmountPress,
handleQuickAmountPress,
currentCurrency,
handleEthInput,
handleFiatInput,
Expand Down Expand Up @@ -121,7 +121,7 @@ const useStakingInputHandlers = () => {
handleKeypadChange,
handleCurrencySwitch,
percentageOptions,
handleAmountPress,
handleQuickAmountPress,
currentCurrency,
conversionRate,
estimatedAnnualRewards,
Expand Down
4 changes: 2 additions & 2 deletions app/components/UI/Stake/hooks/useUnstakingInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const useUnstakingInputHandlers = () => {
handleKeypadChange,
handleCurrencySwitch,
percentageOptions,
handleAmountPress,
handleQuickAmountPress,
currentCurrency,
} = useInputHandler({ balance: new BN(stakedBalanceWei) });

Expand All @@ -39,7 +39,7 @@ const useUnstakingInputHandlers = () => {
handleCurrencySwitch,
currencyToggleValue,
percentageOptions,
handleAmountPress,
handleQuickAmountPress,
handleKeypadChange,
stakedBalanceValue,
};
Expand Down
99 changes: 99 additions & 0 deletions app/components/UI/Stake/utils/metaMetrics/withMetaMetrics.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { withMetaMetrics } from './withMetaMetrics';
import { MetaMetrics } from '../../../../../core/Analytics';
import { MetaMetricsEvents } from '../../../../hooks/useMetrics';

describe('withMetaMetrics', () => {
let trackEventSpy: jest.SpyInstance;

const MOCK_HANDLER_RESULT = 123;
const mockHandler = () => MOCK_HANDLER_RESULT;
const mockAsyncHandler = async () => MOCK_HANDLER_RESULT;

beforeEach(() => {
jest.resetAllMocks();
trackEventSpy = jest.spyOn(MetaMetrics.getInstance(), 'trackEvent');
});

it('fires single event when wrapping sync function', () => {
const mockHandlerWithMetaMetrics = withMetaMetrics(mockHandler, {
event: MetaMetricsEvents.STAKE_BUTTON_CLICKED,
properties: {
sample: 'value',
},
});

const result = mockHandlerWithMetaMetrics();

expect(result).toEqual(MOCK_HANDLER_RESULT);
expect(trackEventSpy).toHaveBeenCalledTimes(1);
});

it('fires array of events when wrapping sync function', () => {
const mockHandlerWithMetaMetrics = withMetaMetrics(mockHandler, [
{
event: MetaMetricsEvents.TOOLTIP_OPENED,
properties: {
selected_provider: 'consensys',
text: 'Tooltip Opened',
location: 'Unit Test',
tooltip_name: 'Test Tooltip 1',
},
},
{
event: MetaMetricsEvents.TOOLTIP_OPENED,
properties: {
selected_provider: 'consensys',
text: 'Tooltip Opened',
location: 'Unit Test',
tooltip_name: 'Test Tooltip 2',
},
},
]);

const result = mockHandlerWithMetaMetrics();
expect(result).toEqual(MOCK_HANDLER_RESULT);
expect(trackEventSpy).toHaveBeenCalledTimes(2);
});

it('fires single event when wrapping async function', async () => {
const mockAsyncHandlerWithMetaMetrics = withMetaMetrics(mockAsyncHandler, {
event: MetaMetricsEvents.STAKE_BUTTON_CLICKED,
properties: {
sample: 'value',
},
});

const result = await mockAsyncHandlerWithMetaMetrics();

expect(result).toEqual(MOCK_HANDLER_RESULT);
expect(trackEventSpy).toHaveBeenCalledTimes(1);
});

it('fires all events when wrapping async function', async () => {
const mockAsyncHandlerWithMetaMetrics = withMetaMetrics(mockAsyncHandler, [
{
event: MetaMetricsEvents.TOOLTIP_OPENED,
properties: {
selected_provider: 'consensys',
text: 'Tooltip Opened',
location: 'Unit Test',
tooltip_name: 'Test Tooltip 1',
},
},
{
event: MetaMetricsEvents.TOOLTIP_OPENED,
properties: {
selected_provider: 'consensys',
text: 'Tooltip Opened',
location: 'Unit Test',
tooltip_name: 'Test Tooltip 2',
},
},
]);

const result = await mockAsyncHandlerWithMetaMetrics();

expect(result).toEqual(MOCK_HANDLER_RESULT);
expect(trackEventSpy).toHaveBeenCalledTimes(2);
});
});
3 changes: 2 additions & 1 deletion app/components/UI/Stake/utils/metaMetrics/withMetaMetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const buildEvent = (e: WithMetaMetricsEvent) => {
return eventBuilder.build();
};

export const withMetaMetrics = <T extends (...args: unknown[]) => unknown>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const withMetaMetrics = <T extends (...args: any[]) => any>(
func: T,
events: WithMetaMetricsEvent | WithMetaMetricsEvent[],
) => {
Expand Down
Loading

0 comments on commit 4a2b689

Please sign in to comment.