From d85c30d512c1dbd6e9aac7ffe4d4e2678d628162 Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:42:08 +0200 Subject: [PATCH 01/11] feat: add stakeSdkProvider and context with stake-sdk --- .../Views/StakeInputView/StakeInputView.tsx | 6 +- app/components/UI/Stake/hooks/useBalance.ts | 2 +- .../UI/Stake/hooks/useStakeContext.ts | 7 + app/components/UI/Stake/routes/index.tsx | 23 +- .../UI/Stake/sdk/UseSdkProvider.test.tsx | 72 + .../UseSdkProvider.test.tsx.snap | 4447 +++++++++++++++++ .../UI/Stake/sdk/stakeSdkProvider.tsx | 75 + app/components/UI/Tokens/index.test.tsx | 27 + app/core/Analytics/MetaMetrics.events.ts | 1 + package.json | 1 + yarn.lock | 9 +- 11 files changed, 4657 insertions(+), 13 deletions(-) create mode 100644 app/components/UI/Stake/hooks/useStakeContext.ts create mode 100644 app/components/UI/Stake/sdk/UseSdkProvider.test.tsx create mode 100644 app/components/UI/Stake/sdk/__snapshots__/UseSdkProvider.test.tsx.snap create mode 100644 app/components/UI/Stake/sdk/stakeSdkProvider.tsx diff --git a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx index 0431e67a77f..58bcc2e6e4a 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 useBalance from '../../hooks/useBalance'; import InputDisplay from '../../components/InputDisplay'; +import { useStakeContext } from '../../hooks/useStakeContext'; const StakeInputView = () => { const title = strings('stake.stake_eth'); @@ -43,6 +44,9 @@ const StakeInputView = () => { estimatedAnnualRewards, } = useStakingInputHandlers(balanceWei); + + const { sdkService } = useStakeContext(); + const navigateToLearnMoreModal = () => { navigation.navigate('StakeModals', { screen: Routes.STAKING.MODALS.LEARN_MORE, @@ -57,7 +61,7 @@ const StakeInputView = () => { amountFiat: fiatAmount, }, }); - }, [amountWei, fiatAmount, navigation]); + }, [amountWei, fiatAmount, navigation, sdkService]); const balanceText = strings('stake.balance'); diff --git a/app/components/UI/Stake/hooks/useBalance.ts b/app/components/UI/Stake/hooks/useBalance.ts index cbe6db124d3..2ce1dfc6af4 100644 --- a/app/components/UI/Stake/hooks/useBalance.ts +++ b/app/components/UI/Stake/hooks/useBalance.ts @@ -48,7 +48,7 @@ const useBalance = () => { [balanceWei, conversionRate], ); - return { balance, balanceFiat, balanceWei, balanceFiatNumber }; + return { balance, balanceFiat, balanceWei, balanceFiatNumber, conversionRate, currentCurrency }; }; export default useBalance; diff --git a/app/components/UI/Stake/hooks/useStakeContext.ts b/app/components/UI/Stake/hooks/useStakeContext.ts new file mode 100644 index 00000000000..b9a9dd46547 --- /dev/null +++ b/app/components/UI/Stake/hooks/useStakeContext.ts @@ -0,0 +1,7 @@ +import { useContext } from "react"; +import { Stake, StakeContext } from "../sdk/stakeSdkProvider"; + +export const useStakeContext = () => { + const context = useContext(StakeContext); + return context as Stake; +}; diff --git a/app/components/UI/Stake/routes/index.tsx b/app/components/UI/Stake/routes/index.tsx index 14993705ca5..a824ed4c24a 100644 --- a/app/components/UI/Stake/routes/index.tsx +++ b/app/components/UI/Stake/routes/index.tsx @@ -5,6 +5,7 @@ import LearnMoreModal from '../components/LearnMoreModal'; import Routes from '../../../../constants/navigation/Routes'; import StakeConfirmationView from '../Views/StakeConfirmationView/StakeConfirmationView'; import UnstakeInputView from '../Views/UnstakeInputView/UnstakeInputView'; +import { StakeSDKProvider } from '../sdk/stakeSdkProvider'; const Stack = createStackNavigator(); const ModalStack = createStackNavigator(); @@ -30,16 +31,18 @@ const StakeScreenStack = () => ( // Modal Stack for Modals const StakeModalStack = () => ( - - - + + + + + ); export { StakeScreenStack, StakeModalStack }; diff --git a/app/components/UI/Stake/sdk/UseSdkProvider.test.tsx b/app/components/UI/Stake/sdk/UseSdkProvider.test.tsx new file mode 100644 index 00000000000..83806bed978 --- /dev/null +++ b/app/components/UI/Stake/sdk/UseSdkProvider.test.tsx @@ -0,0 +1,72 @@ +import { + ChainId, + PooledStakingContract, + StakingType, +} from '@metamask/stake-sdk'; +import renderWithProvider from '../../../../util/test/renderWithProvider'; +import { createStackNavigator } from '@react-navigation/stack'; +import { backgroundState } from '../../../../util/test/initial-root-state'; +import { Stake } from '../sdk/stakeSdkProvider'; +import * as useStakeContextHook from '../hooks/useStakeContext'; +import { Contract } from '@ethersproject/contracts'; +import { StakeModalStack, StakeScreenStack } from '../routes'; + +const mockPooledStakingContractService: PooledStakingContract = { + chainId: ChainId.ETHEREUM, + connectSignerOrProvider: jest.fn(), + contract: new Contract('0x0000000000000000000000000000000000000000', []), + convertToShares: jest.fn(), + encodeClaimExitedAssetsTransactionData: jest.fn(), + encodeDepositTransactionData: jest.fn(), + encodeEnterExitQueueTransactionData: jest.fn(), + encodeMulticallTransactionData: jest.fn(), + estimateClaimExitedAssetsGas: jest.fn(), + estimateDepositGas: jest.fn(), + estimateEnterExitQueueGas: jest.fn(), + estimateMulticallGas: jest.fn(), +}; + +const mockSDK: Stake = { + sdkService: mockPooledStakingContractService, + sdkType: StakingType.POOLED, + setSdkType: jest.fn(), +}; + +jest.mock('../../Stake/constants', () => ({ + isPooledStakingFeatureEnabled: jest.fn().mockReturnValue(true), +})); + +describe('Stake Modals With Stake Sdk Provider', () => { + const initialState = { + engine: { + backgroundState, + }, + }; + + it('should render correctly stake screen with stake sdk provider and resolve the stake context', () => { + const useStakeContextSpy = jest + .spyOn(useStakeContextHook, 'useStakeContext') + .mockReturnValue(mockSDK); + + const { toJSON } = renderWithProvider(StakeScreenStack(), { + state: initialState, + }); + + expect(toJSON()).toMatchSnapshot(); + expect(useStakeContextSpy).toHaveBeenCalled(); + }); + + it('should render correctly stake modal with stake sdk provider and resolve the stake context', () => { + const useStakeContextSpy = jest + .spyOn(useStakeContextHook, 'useStakeContext') + .mockReturnValue(mockSDK); + + const { toJSON } = renderWithProvider(StakeModalStack(), { + state: initialState, + }); + + expect(toJSON()).toMatchSnapshot(); + expect(useStakeContextSpy).toHaveBeenCalledTimes(0); + + }); +}); diff --git a/app/components/UI/Stake/sdk/__snapshots__/UseSdkProvider.test.tsx.snap b/app/components/UI/Stake/sdk/__snapshots__/UseSdkProvider.test.tsx.snap new file mode 100644 index 00000000000..49953c439a0 --- /dev/null +++ b/app/components/UI/Stake/sdk/__snapshots__/UseSdkProvider.test.tsx.snap @@ -0,0 +1,4447 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Stake Modals With Stake Sdk Provider should render correctly stake modal with stake sdk provider 1`] = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + Stake ETH and earn + + + + + Stake any amount of ETH + + + No minimum required. + + + + + Earn ETH rewards + + + Start earning as soon as you stake. Rewards compound automatically. + + + + + Flexible unstaking + + + Unstake anytime. Typically takes up to 11 days to process. + + + + + Staking does not guarantee rewards, and involves risks including a loss of funds. + + + + + + + + Learn more + + + + + + + Got it + + + + + + + + + + + + + + + + + + +`; + +exports[`Stake Modals With Stake Sdk Provider should render correctly stake modal with stake sdk provider and resolve the stake context 1`] = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + Stake ETH and earn + + + + + Stake any amount of ETH + + + No minimum required. + + + + + Earn ETH rewards + + + Start earning as soon as you stake. Rewards compound automatically. + + + + + Flexible unstaking + + + Unstake anytime. Typically takes up to 11 days to process. + + + + + Staking does not guarantee rewards, and involves risks including a loss of funds. + + + + + + + + Learn more + + + + + + + Got it + + + + + + + + + + + + + + + + + + +`; + +exports[`Stake Modals With Stake Sdk Provider should render correctly stake screen with stake sdk provider 1`] = ` + + + + + + + + + + + + + Stake ETH + + + + + + Cancel + + + + + + + + + + + + + + + + + + + + + + + Balance + : + 0 ETH + + + + + 0 + + + ETH + + + + + + 0 USD + + + + + + + + + + + MetaMask Pool + + + + + + + + 2.6% + + + Estimated annual rewards + + + + + + + + + 25% + + + + + 50% + + + + + 75% + + + + + + Max + + + + + + + + 1 + + + + + 2 + + + + + 3 + + + + + + + 4 + + + + + 5 + + + + + 6 + + + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + . + + + + + 0 + + + + +  + + + + + + + + Enter amount + + + + + + + + + + + + + + + +`; + +exports[`Stake Modals With Stake Sdk Provider should render correctly stake screen with stake sdk provider and resolve the stake context 1`] = ` + + + + + + + + + + + + + Stake ETH + + + + + + Cancel + + + + + + + + + + + + + + + + + + + + + + + Balance + : + 0 ETH + + + + + 0 + + + ETH + + + + + + 0 USD + + + + + + + + + + + MetaMask Pool + + + + + + + + 2.6% + + + Estimated annual rewards + + + + + + + + + 25% + + + + + 50% + + + + + 75% + + + + + + Max + + + + + + + + 1 + + + + + 2 + + + + + 3 + + + + + + + 4 + + + + + 5 + + + + + 6 + + + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + . + + + + + 0 + + + + +  + + + + + + + + Enter amount + + + + + + + + + + + + + + + +`; diff --git a/app/components/UI/Stake/sdk/stakeSdkProvider.tsx b/app/components/UI/Stake/sdk/stakeSdkProvider.tsx new file mode 100644 index 00000000000..04b04688be4 --- /dev/null +++ b/app/components/UI/Stake/sdk/stakeSdkProvider.tsx @@ -0,0 +1,75 @@ +import { StakingType, StakeSdk, PooledStakingContract } from '@metamask/stake-sdk'; +import Logger from '../../../../util/Logger'; +import React, { + useState, + useEffect, + createContext, + useContext, + useMemo, + FC, + PropsWithChildren, +} from 'react'; + +export const SDK = StakeSdk.create({ stakingType: StakingType.POOLED }); + +export interface Stake { + sdkError?: Error; + sdkService?: PooledStakingContract; // to do : facade it for other services implementation + + sdkType?: StakingType; + setSdkType: (stakeType: StakingType) => void; +} + +export const StakeContext = createContext(undefined); + +export interface StakeProviderProps { + stakingType?: StakingType; +} +export const StakeSDKProvider: React.FC> = ({ + children, + ...props +}) => { + // from react state + const [sdkService, setSdkService] = useState(); + const [sdkError, setSdkError] = useState(); + const [sdkType, setSdkType] = useState(StakingType.POOLED); + + useEffect(() => { + (async () => { + try { + if (sdkType === StakingType?.POOLED) { + setSdkService(SDK.pooledStakingContractService); + } else { + const notImplementedError = new Error( + `StakeSDKProvider SDK.StakingType ${sdkType} not implemented yet`, + ); + Logger.error(notImplementedError); + setSdkError(notImplementedError); + } + } catch (error) { + Logger.error(error as Error, `StakeSDKProvider SDK.service failed`); + setSdkError(error as Error); + } + })(); + }, [sdkType]); + + const stakeContextValue = useMemo( + (): Stake => ({ + sdkError, + sdkService, + sdkType, + setSdkType, + }), + [ + sdkError, + sdkService, + sdkType, + setSdkType, + ], + ); + return ( + + {children} + + ); +}; \ No newline at end of file diff --git a/app/components/UI/Tokens/index.test.tsx b/app/components/UI/Tokens/index.test.tsx index b01f5f25866..55641d87d16 100644 --- a/app/components/UI/Tokens/index.test.tsx +++ b/app/components/UI/Tokens/index.test.tsx @@ -11,6 +11,7 @@ import { strings } from '../../../../locales/i18n'; import AppConstants from '../../../../app/core/AppConstants'; import Routes from '../../../../app/constants/navigation/Routes'; import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/wallet/WalletView.selectors'; +import { MetaMetricsEvents, useMetrics } from '../../../../app/components/hooks/useMetrics'; jest.mock('../../../core/Engine', () => ({ getTotalFiatAccountBalance: jest.fn(), @@ -104,6 +105,10 @@ jest.mock('@react-navigation/native', () => { }; }); +jest.mock('../../../components/hooks/useMetrics', () => ({ + useMetrics: jest.fn(), +})); + const Stack = createStackNavigator(); // TODO: Replace "any" with type // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -123,6 +128,12 @@ const renderComponent = (state: any = {}) => ); describe('Tokens', () => { + beforeEach(() => { + (useMetrics as jest.Mock).mockReturnValue({ + trackEvent: jest.fn(), + }); + }) + afterEach(() => { mockNavigate.mockClear(); mockPush.mockClear(); @@ -256,6 +267,11 @@ describe('Tokens', () => { expect(getByTestId(WalletViewSelectorsIDs.STAKE_BUTTON)).toBeDefined(); }); it('navigates to Portfolio Stake url when stake button is pressed', () => { + const trackEvent = jest.fn(); + (useMetrics as jest.Mock).mockReturnValue({ + trackEvent, + }); + const { getByTestId } = renderComponent(initialState); fireEvent.press(getByTestId(WalletViewSelectorsIDs.STAKE_BUTTON)); @@ -266,5 +282,16 @@ describe('Tokens', () => { }, screen: Routes.BROWSER.VIEW, }); + expect(trackEvent).toHaveBeenNthCalledWith( + 1, + MetaMetricsEvents.STAKE_BUTTON_CLICKED, + { + chain_id: expect.any(String), + location: 'Home Screen', + text: 'Stake', + token_symbol: expect.any(String), + url: AppConstants.STAKE.URL, + } + ); }); }); diff --git a/app/core/Analytics/MetaMetrics.events.ts b/app/core/Analytics/MetaMetrics.events.ts index d15622a6aac..e0c2be95228 100644 --- a/app/core/Analytics/MetaMetrics.events.ts +++ b/app/core/Analytics/MetaMetrics.events.ts @@ -1222,6 +1222,7 @@ const legacyMetaMetricsEvents = { ACTIONS.BRIDGE, DESCRIPTION.BRIDGE, ), + // Stake STAKE_BUTTON_CLICKED: generateOpt( EVENT_NAME.STAKE_BUTTON_CLICKED, ACTIONS.STAKE, diff --git a/package.json b/package.json index 1b811292afe..64e61864089 100644 --- a/package.json +++ b/package.json @@ -183,6 +183,7 @@ "@metamask/snaps-rpc-methods": "^9.1.4", "@metamask/snaps-sdk": "^6.5.0", "@metamask/snaps-utils": "^8.1.1", + "@metamask/stake-sdk": "^0.2.11", "@metamask/swappable-obj-proxy": "^2.1.0", "@metamask/swaps-controller": "^9.0.12", "@metamask/transaction-controller": "^37.1.0", diff --git a/yarn.lock b/yarn.lock index 4d2b39ab497..1e3eb8b3669 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5532,6 +5532,13 @@ ses "^1.1.0" validate-npm-package-name "^5.0.0" +"@metamask/stake-sdk@^0.2.11": + version "0.2.11" + resolved "https://registry.yarnpkg.com/@metamask/stake-sdk/-/stake-sdk-0.2.11.tgz#70b003a7b7f5208fad0d5a986aedd84b0987979f" + integrity sha512-l2novyUK7oVKO2vZDd2tCSyQ8e468hWp0ZB3ed2FoR61HGlZDMqv3hDtXPAfOeA0+cQwsZM861yoUdSXNo0WPA== + dependencies: + axios "^1.7.7" + "@metamask/superstruct@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@metamask/superstruct/-/superstruct-3.1.0.tgz#148f786a674fba3ac885c1093ab718515bf7f648" @@ -12962,7 +12969,7 @@ axios-retry@^3.1.2: "@babel/runtime" "^7.15.4" is-retry-allowed "^2.2.0" -axios@1.4.0, axios@^0.26.0, axios@^0.28.0, axios@^0.x, axios@^1.6.7, axios@^1.6.8, axios@^1.7.4, axios@~1.6.8: +axios@1.4.0, axios@^0.26.0, axios@^0.28.0, axios@^0.x, axios@^1.6.7, axios@^1.6.8, axios@^1.7.4, axios@^1.7.7, axios@~1.6.8: version "1.7.4" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== From d6bc8bfdfbde05bc4db576b82d80e49bec310c49 Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:13:29 +0200 Subject: [PATCH 02/11] fix: unit test --- app/components/UI/Tokens/index.test.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/components/UI/Tokens/index.test.tsx b/app/components/UI/Tokens/index.test.tsx index 55641d87d16..a4c5ac3f727 100644 --- a/app/components/UI/Tokens/index.test.tsx +++ b/app/components/UI/Tokens/index.test.tsx @@ -109,6 +109,10 @@ jest.mock('../../../components/hooks/useMetrics', () => ({ useMetrics: jest.fn(), })); +jest.mock('../../../components/hooks/useMetrics', () => ({ + useMetrics: jest.fn(), +})); + const Stack = createStackNavigator(); // TODO: Replace "any" with type // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -128,6 +132,12 @@ const renderComponent = (state: any = {}) => ); describe('Tokens', () => { + beforeEach(() => { + (useMetrics as jest.Mock).mockReturnValue({ + trackEvent: jest.fn(), + }); + }); + beforeEach(() => { (useMetrics as jest.Mock).mockReturnValue({ trackEvent: jest.fn(), From d5060e6a733d5f380da730effce6d810826af3c7 Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:31:24 +0200 Subject: [PATCH 03/11] chore: yarn lint and fix test --- .../UI/Stake/Views/StakeInputView/StakeInputView.tsx | 1 + app/components/UI/Stake/hooks/useStakeContext.ts | 4 ++-- app/components/UI/Stake/sdk/UseSdkProvider.test.tsx | 3 +-- app/components/UI/Stake/sdk/stakeSdkProvider.tsx | 3 --- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx index 58bcc2e6e4a..782e4d5ab3c 100644 --- a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx +++ b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx @@ -61,6 +61,7 @@ const StakeInputView = () => { amountFiat: fiatAmount, }, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [amountWei, fiatAmount, navigation, sdkService]); const balanceText = strings('stake.balance'); diff --git a/app/components/UI/Stake/hooks/useStakeContext.ts b/app/components/UI/Stake/hooks/useStakeContext.ts index b9a9dd46547..0fc280593da 100644 --- a/app/components/UI/Stake/hooks/useStakeContext.ts +++ b/app/components/UI/Stake/hooks/useStakeContext.ts @@ -1,5 +1,5 @@ -import { useContext } from "react"; -import { Stake, StakeContext } from "../sdk/stakeSdkProvider"; +import { useContext } from 'react'; +import { Stake, StakeContext } from '../sdk/stakeSdkProvider'; export const useStakeContext = () => { const context = useContext(StakeContext); diff --git a/app/components/UI/Stake/sdk/UseSdkProvider.test.tsx b/app/components/UI/Stake/sdk/UseSdkProvider.test.tsx index 83806bed978..6c47a20406c 100644 --- a/app/components/UI/Stake/sdk/UseSdkProvider.test.tsx +++ b/app/components/UI/Stake/sdk/UseSdkProvider.test.tsx @@ -4,9 +4,9 @@ import { StakingType, } from '@metamask/stake-sdk'; import renderWithProvider from '../../../../util/test/renderWithProvider'; -import { createStackNavigator } from '@react-navigation/stack'; import { backgroundState } from '../../../../util/test/initial-root-state'; import { Stake } from '../sdk/stakeSdkProvider'; +// eslint-disable-next-line import/no-namespace import * as useStakeContextHook from '../hooks/useStakeContext'; import { Contract } from '@ethersproject/contracts'; import { StakeModalStack, StakeScreenStack } from '../routes'; @@ -42,7 +42,6 @@ describe('Stake Modals With Stake Sdk Provider', () => { backgroundState, }, }; - it('should render correctly stake screen with stake sdk provider and resolve the stake context', () => { const useStakeContextSpy = jest .spyOn(useStakeContextHook, 'useStakeContext') diff --git a/app/components/UI/Stake/sdk/stakeSdkProvider.tsx b/app/components/UI/Stake/sdk/stakeSdkProvider.tsx index 04b04688be4..60b36e4d26f 100644 --- a/app/components/UI/Stake/sdk/stakeSdkProvider.tsx +++ b/app/components/UI/Stake/sdk/stakeSdkProvider.tsx @@ -4,9 +4,7 @@ import React, { useState, useEffect, createContext, - useContext, useMemo, - FC, PropsWithChildren, } from 'react'; @@ -27,7 +25,6 @@ export interface StakeProviderProps { } export const StakeSDKProvider: React.FC> = ({ children, - ...props }) => { // from react state const [sdkService, setSdkService] = useState(); From 7dc741b40b934e24a895597766e703a967435b24 Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:10:29 +0200 Subject: [PATCH 04/11] fix: unit test stakeinputview --- .../Views/StakeInputView/StakeInputView.test.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.test.tsx b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.test.tsx index 10ac002beb1..9648fba601e 100644 --- a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.test.tsx +++ b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.test.tsx @@ -5,6 +5,7 @@ import { renderScreen } from '../../../../../util/test/renderWithProvider'; import Routes from '../../../../../constants/navigation/Routes'; import { backgroundState } from '../../../../../util/test/initial-root-state'; import { BN } from 'ethereumjs-util'; +import { Stake } from '../../sdk/stakeSdkProvider'; function render(Component: React.ComponentType) { return renderScreen( @@ -51,6 +52,17 @@ jest.mock('../../../../../selectors/currencyRateController.ts', () => ({ })); const mockBalanceBN = new BN('1500000000000000000'); + +jest.mock('../../hooks/useStakeContext.ts', () => ({ + useStakeContext: jest.fn(() => { + const stakeContext: Stake = { + setSdkType: jest.fn(), + sdkService: undefined + } + return stakeContext + }) +})) + jest.mock('../../hooks/useBalance', () => ({ __esModule: true, default: () => ({ From f27c825958f24b48a217431021bb5f1880f5f6bb Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:54:34 +0200 Subject: [PATCH 05/11] chore: remove stake analytic event mock --- app/components/UI/Tokens/index.test.tsx | 37 ------------------------- 1 file changed, 37 deletions(-) diff --git a/app/components/UI/Tokens/index.test.tsx b/app/components/UI/Tokens/index.test.tsx index a4c5ac3f727..b01f5f25866 100644 --- a/app/components/UI/Tokens/index.test.tsx +++ b/app/components/UI/Tokens/index.test.tsx @@ -11,7 +11,6 @@ import { strings } from '../../../../locales/i18n'; import AppConstants from '../../../../app/core/AppConstants'; import Routes from '../../../../app/constants/navigation/Routes'; import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/wallet/WalletView.selectors'; -import { MetaMetricsEvents, useMetrics } from '../../../../app/components/hooks/useMetrics'; jest.mock('../../../core/Engine', () => ({ getTotalFiatAccountBalance: jest.fn(), @@ -105,14 +104,6 @@ jest.mock('@react-navigation/native', () => { }; }); -jest.mock('../../../components/hooks/useMetrics', () => ({ - useMetrics: jest.fn(), -})); - -jest.mock('../../../components/hooks/useMetrics', () => ({ - useMetrics: jest.fn(), -})); - const Stack = createStackNavigator(); // TODO: Replace "any" with type // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -132,18 +123,6 @@ const renderComponent = (state: any = {}) => ); describe('Tokens', () => { - beforeEach(() => { - (useMetrics as jest.Mock).mockReturnValue({ - trackEvent: jest.fn(), - }); - }); - - beforeEach(() => { - (useMetrics as jest.Mock).mockReturnValue({ - trackEvent: jest.fn(), - }); - }) - afterEach(() => { mockNavigate.mockClear(); mockPush.mockClear(); @@ -277,11 +256,6 @@ describe('Tokens', () => { expect(getByTestId(WalletViewSelectorsIDs.STAKE_BUTTON)).toBeDefined(); }); it('navigates to Portfolio Stake url when stake button is pressed', () => { - const trackEvent = jest.fn(); - (useMetrics as jest.Mock).mockReturnValue({ - trackEvent, - }); - const { getByTestId } = renderComponent(initialState); fireEvent.press(getByTestId(WalletViewSelectorsIDs.STAKE_BUTTON)); @@ -292,16 +266,5 @@ describe('Tokens', () => { }, screen: Routes.BROWSER.VIEW, }); - expect(trackEvent).toHaveBeenNthCalledWith( - 1, - MetaMetricsEvents.STAKE_BUTTON_CLICKED, - { - chain_id: expect.any(String), - location: 'Home Screen', - text: 'Stake', - token_symbol: expect.any(String), - url: AppConstants.STAKE.URL, - } - ); }); }); From e2f793bee7737b8b5e7ba589dbdc7866a16557fc Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:06:08 +0200 Subject: [PATCH 06/11] fix: update snapshot usesdkprovider test --- .../UseSdkProvider.test.tsx.snap | 2225 +---------------- 1 file changed, 1 insertion(+), 2224 deletions(-) diff --git a/app/components/UI/Stake/sdk/__snapshots__/UseSdkProvider.test.tsx.snap b/app/components/UI/Stake/sdk/__snapshots__/UseSdkProvider.test.tsx.snap index 49953c439a0..12944c1a6ce 100644 --- a/app/components/UI/Stake/sdk/__snapshots__/UseSdkProvider.test.tsx.snap +++ b/app/components/UI/Stake/sdk/__snapshots__/UseSdkProvider.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Stake Modals With Stake Sdk Provider should render correctly stake modal with stake sdk provider 1`] = ` +exports[`Stake Modals With Stake Sdk Provider should render correctly stake modal with stake sdk provider and resolve the stake context 1`] = ` `; -exports[`Stake Modals With Stake Sdk Provider should render correctly stake modal with stake sdk provider and resolve the stake context 1`] = ` - - - - - - - - - - - - - - - - - - - - - - - - - - - Stake ETH and earn - - - - - Stake any amount of ETH - - - No minimum required. - - - - - Earn ETH rewards - - - Start earning as soon as you stake. Rewards compound automatically. - - - - - Flexible unstaking - - - Unstake anytime. Typically takes up to 11 days to process. - - - - - Staking does not guarantee rewards, and involves risks including a loss of funds. - - - - - - - - Learn more - - - - - - - Got it - - - - - - - - - - - - - - - - - - -`; - -exports[`Stake Modals With Stake Sdk Provider should render correctly stake screen with stake sdk provider 1`] = ` - - - - - - - - - - - - - Stake ETH - - - - - - Cancel - - - - - - - - - - - - - - - - - - - - - - - Balance - : - 0 ETH - - - - - 0 - - - ETH - - - - - - 0 USD - - - - - - - - - - - MetaMask Pool - - - - - - - - 2.6% - - - Estimated annual rewards - - - - - - - - - 25% - - - - - 50% - - - - - 75% - - - - - - Max - - - - - - - - 1 - - - - - 2 - - - - - 3 - - - - - - - 4 - - - - - 5 - - - - - 6 - - - - - - - 7 - - - - - 8 - - - - - 9 - - - - - - - . - - - - - 0 - - - - -  - - - - - - - - Enter amount - - - - - - - - - - - - - - - -`; - exports[`Stake Modals With Stake Sdk Provider should render correctly stake screen with stake sdk provider and resolve the stake context 1`] = ` Date: Thu, 17 Oct 2024 16:30:09 +0200 Subject: [PATCH 07/11] chore: add stake provider on screen stack --- app/components/UI/Stake/routes/index.tsx | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/app/components/UI/Stake/routes/index.tsx b/app/components/UI/Stake/routes/index.tsx index a824ed4c24a..73960d4a7af 100644 --- a/app/components/UI/Stake/routes/index.tsx +++ b/app/components/UI/Stake/routes/index.tsx @@ -19,14 +19,19 @@ const clearStackNavigatorOptions = { // Regular Stack for Screens const StakeScreenStack = () => ( - - - - - + + + + + + + ); // Modal Stack for Modals From 65c72c832ebd71b43a9af26b37f04bc169e112ae Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:01:47 +0200 Subject: [PATCH 08/11] chore: remove comment from metametrics event file --- app/core/Analytics/MetaMetrics.events.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/core/Analytics/MetaMetrics.events.ts b/app/core/Analytics/MetaMetrics.events.ts index e0c2be95228..22b6bac089b 100644 --- a/app/core/Analytics/MetaMetrics.events.ts +++ b/app/core/Analytics/MetaMetrics.events.ts @@ -273,7 +273,6 @@ enum EVENT_NAME { // Bridge BRIDGE_LINK_CLICKED = 'Bridge Linked Clicked', - // Stake STAKE_BUTTON_CLICKED = 'Stake Button Clicked', // Force Upgrade | Automatic Security Checks From 9a565f71694a2a58e6f08cbf69893a2f99ecb6c6 Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:03:36 +0200 Subject: [PATCH 09/11] Revert "chore: remove comment from metametrics event file" This reverts commit 65c72c832ebd71b43a9af26b37f04bc169e112ae. --- app/core/Analytics/MetaMetrics.events.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/core/Analytics/MetaMetrics.events.ts b/app/core/Analytics/MetaMetrics.events.ts index 22b6bac089b..e0c2be95228 100644 --- a/app/core/Analytics/MetaMetrics.events.ts +++ b/app/core/Analytics/MetaMetrics.events.ts @@ -273,6 +273,7 @@ enum EVENT_NAME { // Bridge BRIDGE_LINK_CLICKED = 'Bridge Linked Clicked', + // Stake STAKE_BUTTON_CLICKED = 'Stake Button Clicked', // Force Upgrade | Automatic Security Checks From 7c4957c8dfa76f4bc2226a26c71b8cb9c79fac1c Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:06:09 +0200 Subject: [PATCH 10/11] chore: remove duplicate comment --- app/core/Analytics/MetaMetrics.events.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/core/Analytics/MetaMetrics.events.ts b/app/core/Analytics/MetaMetrics.events.ts index e0c2be95228..d15622a6aac 100644 --- a/app/core/Analytics/MetaMetrics.events.ts +++ b/app/core/Analytics/MetaMetrics.events.ts @@ -1222,7 +1222,6 @@ const legacyMetaMetricsEvents = { ACTIONS.BRIDGE, DESCRIPTION.BRIDGE, ), - // Stake STAKE_BUTTON_CLICKED: generateOpt( EVENT_NAME.STAKE_BUTTON_CLICKED, ACTIONS.STAKE, From 56ecea8fd2b717092b9a2324a070d2ae2b515fdd Mon Sep 17 00:00:00 2001 From: siibars <9662464+siibars@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:19:54 +0200 Subject: [PATCH 11/11] chore: remove comment --- app/components/UI/Stake/sdk/stakeSdkProvider.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/components/UI/Stake/sdk/stakeSdkProvider.tsx b/app/components/UI/Stake/sdk/stakeSdkProvider.tsx index 60b36e4d26f..19a6769949b 100644 --- a/app/components/UI/Stake/sdk/stakeSdkProvider.tsx +++ b/app/components/UI/Stake/sdk/stakeSdkProvider.tsx @@ -26,7 +26,6 @@ export interface StakeProviderProps { export const StakeSDKProvider: React.FC> = ({ children, }) => { - // from react state const [sdkService, setSdkService] = useState(); const [sdkError, setSdkError] = useState(); const [sdkType, setSdkType] = useState(StakingType.POOLED);