Skip to content

Commit

Permalink
Stake 806 to uat (#11912)
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**
PR from [this
one](#11891) onto a uat
branch so that we can create a QA release from it.
<!--
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-806

## **Manual testing steps**

1. When merged get the apk built from the test/mobile-staking-uat branch
and test it on your device.

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **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.

---------

Co-authored-by: Amitabh Aggarwal <aggarwal.amitabh@gmail.com>
  • Loading branch information
siibars and amitabh94 authored Oct 21, 2024
1 parent 59c0f11 commit ced542a
Show file tree
Hide file tree
Showing 40 changed files with 895 additions and 384 deletions.
6 changes: 4 additions & 2 deletions app/components/UI/AssetOverview/Balance/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ interface BalanceProps {
secondaryBalance?: string;
}

const NetworkBadgeSource = (chainId: string, ticker: string) => {
export const NetworkBadgeSource = (chainId: string, ticker: string) => {
const isMainnet = isMainnetByChainId(chainId);
const isLineaMainnet = isLineaMainnetByChainId(chainId);

Expand Down Expand Up @@ -88,7 +88,9 @@ const Balance = ({ asset, mainBalance, secondaryBalance }: BalanceProps) => {
{asset.name || asset.symbol}
</Text>
</AssetElement>
{isPooledStakingFeatureEnabled() && asset?.isETH && <StakingBalance />}
{isPooledStakingFeatureEnabled() && asset?.isETH && (
<StakingBalance asset={asset} />
)}
</View>
);
};
Expand Down
11 changes: 3 additions & 8 deletions app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { zeroAddress } from 'ethereumjs-util';
import React, { useState } from 'react';
import React from 'react';
import { View } from 'react-native';
import { useSelector } from 'react-redux';
import i18n from '../../../../../locales/i18n';
Expand All @@ -21,8 +21,8 @@ import Logger from '../../../../util/Logger';
import TokenDetailsList from './TokenDetailsList';
import MarketDetailsList from './MarketDetailsList';
import { TokenI } from '../../Tokens/types';
import StakingEarnings from '../StakingEarnings';
import { isPooledStakingFeatureEnabled } from '../../Stake/constants';
import StakingEarnings from '../../Stake/components/StakingEarnings';

export interface TokenDetails {
contractAddress: string | null;
Expand Down Expand Up @@ -52,9 +52,6 @@ const TokenDetails: React.FC<TokenDetailsProps> = ({ asset }) => {
const currentCurrency = useSelector(selectCurrentCurrency);
const tokenContractAddress = safeToChecksumAddress(asset.address);

// TEMP: Remove once component has been implemented.
const [hasStakingPositions] = useState(true);

let tokenMetadata;
let marketData;

Expand Down Expand Up @@ -126,9 +123,7 @@ const TokenDetails: React.FC<TokenDetailsProps> = ({ asset }) => {

return (
<View style={styles.tokenDetailsContainer}>
{asset.isETH &&
hasStakingPositions &&
isPooledStakingFeatureEnabled() && <StakingEarnings />}
{asset.isETH && isPooledStakingFeatureEnabled() && <StakingEarnings />}
{(asset.isETH || tokenMetadata) && (
<TokenDetailsList tokenDetails={tokenDetails} />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ describe('StakeConfirmationView', () => {
const props: StakeConfirmationViewProps = {
route: {
key: '1',
params: { amountWei: '3210000000000000', amountFiat: '7.46' },
params: {
amountWei: '3210000000000000',
amountFiat: '7.46',
annualRewardRate: '2.5%',
annualRewardsETH: '2.5 ETH',
annualRewardsFiat: '$5000',
},
name: 'params',
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,8 @@ import AccountHeaderCard from '../../components/StakingConfirmation/AccountHeade
import RewardsCard from '../../components/StakingConfirmation/RewardsCard/RewardsCard';
import ConfirmationFooter from '../../components/StakingConfirmation/ConfirmationFooter/ConfirmationFooter';
import { StakeConfirmationViewProps } from './StakeConfirmationView.types';
import { MOCK_GET_VAULT_RESPONSE } from '../../components/StakingBalance/mockData';
import { strings } from '../../../../../../locales/i18n';

const MOCK_REWARD_DATA = {
REWARDS: {
ETH: '0.13 ETH',
FIAT: '$334.93',
},
};

const MOCK_STAKING_CONTRACT_NAME = 'MM Pooled Staking';

const StakeConfirmationView = ({ route }: StakeConfirmationViewProps) => {
Expand Down Expand Up @@ -46,9 +38,9 @@ const StakeConfirmationView = ({ route }: StakeConfirmationViewProps) => {
<View style={styles.cardsContainer}>
<AccountHeaderCard contractName={MOCK_STAKING_CONTRACT_NAME} />
<RewardsCard
rewardRate={MOCK_GET_VAULT_RESPONSE.apy}
rewardsEth={MOCK_REWARD_DATA.REWARDS.ETH}
rewardsFiat={MOCK_REWARD_DATA.REWARDS.FIAT}
rewardRate={route.params.annualRewardRate}
rewardsEth={route.params.annualRewardsETH}
rewardsFiat={route.params.annualRewardsFiat}
/>
</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { RouteProp } from '@react-navigation/native';
interface StakeConfirmationViewRouteParams {
amountWei: string;
amountFiat: string;
annualRewardsETH: string;
annualRewardsFiat: string;
annualRewardRate: string;
}

export interface StakeConfirmationViewProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@ exports[`StakeConfirmationView render matches snapshot 1`] = `
}
testID="label"
>
2.8%
2.5%
</Text>
</View>
</View>
Expand Down Expand Up @@ -1100,7 +1100,7 @@ exports[`StakeConfirmationView render matches snapshot 1`] = `
}
}
>
$334.93
$5000
</Text>
<Text
accessibilityRole="text"
Expand All @@ -1115,7 +1115,7 @@ exports[`StakeConfirmationView render matches snapshot 1`] = `
}
}
>
0.13 ETH
2.5 ETH
</Text>
</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Routes from '../../../../../constants/navigation/Routes';
import { backgroundState } from '../../../../../util/test/initial-root-state';
import { BN } from 'ethereumjs-util';
import { Stake } from '../../sdk/stakeSdkProvider';
import { MOCK_GET_VAULT_RESPONSE } from '../../__mocks__/mockData';

function render(Component: React.ComponentType) {
return renderScreen(
Expand Down Expand Up @@ -57,11 +58,11 @@ jest.mock('../../hooks/useStakeContext.ts', () => ({
useStakeContext: jest.fn(() => {
const stakeContext: Stake = {
setSdkType: jest.fn(),
sdkService: undefined
}
return stakeContext
})
}))
stakingContract: undefined,
};
return stakeContext;
}),
}));

jest.mock('../../hooks/useBalance', () => ({
__esModule: true,
Expand All @@ -72,6 +73,31 @@ jest.mock('../../hooks/useBalance', () => ({
}),
}));

const mockVaultData = MOCK_GET_VAULT_RESPONSE;
// Mock hooks

jest.mock('../../hooks/useStakingEligibility', () => ({
__esModule: true,
default: () => ({
isEligible: true,
loading: false,
error: null,
refreshPooledStakingEligibility: jest.fn(),
}),
}));

jest.mock('../../hooks/useVaultData', () => ({
__esModule: true,
default: () => ({
vaultData: mockVaultData,
loading: false,
error: null,
refreshVaultData: jest.fn(),
annualRewardRate: '2.5%',
annualRewardRateDecimal: 0.025,
}),
}));

describe('StakeInputView', () => {
it('render matches snapshot', () => {
render(StakeInputView);
Expand Down Expand Up @@ -105,7 +131,7 @@ describe('StakeInputView', () => {

fireEvent.press(screen.getByText('2'));

expect(screen.getByText('0.052 ETH')).toBeTruthy();
expect(screen.getByText('0.05 ETH')).toBeTruthy();
});
});

Expand Down
22 changes: 16 additions & 6 deletions app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ 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');
Expand All @@ -42,11 +41,12 @@ const StakeInputView = () => {
handleKeypadChange,
calculateEstimatedAnnualRewards,
estimatedAnnualRewards,
annualRewardsEth: annualRewardsETH,
annualRewardsFiat,
annualRewardRate,
isLoadingVaultData,
} = useStakingInputHandlers(balanceWei);


const { sdkService } = useStakeContext();

const navigateToLearnMoreModal = () => {
navigation.navigate('StakeModals', {
screen: Routes.STAKING.MODALS.LEARN_MORE,
Expand All @@ -59,10 +59,19 @@ const StakeInputView = () => {
params: {
amountWei: amountWei.toString(),
amountFiat: fiatAmount,
annualRewardsETH,
annualRewardsFiat,
annualRewardRate,
},
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [amountWei, fiatAmount, navigation, sdkService]);
}, [
navigation,
amountWei,
fiatAmount,
annualRewardsETH,
annualRewardsFiat,
annualRewardRate,
]);

const balanceText = strings('stake.balance');

Expand Down Expand Up @@ -106,6 +115,7 @@ const StakeInputView = () => {
<EstimatedAnnualRewardsCard
estimatedAnnualRewards={estimatedAnnualRewards}
onIconPress={navigateToLearnMoreModal}
isLoading={isLoadingVaultData}
/>
</View>
<QuickAmounts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ exports[`StakeInputView render matches snapshot 1`] = `
}
}
>
2.6%
2.5%
</Text>
<Text
accessibilityRole="text"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import UnstakeInputView from './UnstakeInputView';
import { renderScreen } from '../../../../../util/test/renderWithProvider';
import Routes from '../../../../../constants/navigation/Routes';
import { backgroundState } from '../../../../../util/test/initial-root-state';
import {
MOCK_GET_POOLED_STAKES_API_RESPONSE,
MOCK_GET_VAULT_RESPONSE,
MOCK_STAKED_ETH_ASSET,
} from '../../__mocks__/mockData';

function render(Component: React.ComponentType) {
return renderScreen(
Expand Down Expand Up @@ -48,6 +53,38 @@ jest.mock('../../../../../selectors/currencyRateController.ts', () => ({
selectCurrentCurrency: jest.fn(() => 'USD'),
}));

const mockVaultData = MOCK_GET_VAULT_RESPONSE;
const mockPooledStakeData = MOCK_GET_POOLED_STAKES_API_RESPONSE.accounts[0];

jest.mock('../../hooks/useStakingEligibility', () => ({
__esModule: true,
default: () => ({
isEligible: true,
loading: false,
error: null,
refreshPooledStakingEligibility: jest.fn(),
}),
}));

jest.mock('../../hooks/useVaultData', () => ({
__esModule: true,
default: () => ({
vaultData: mockVaultData,
loading: false,
error: null,
annualRewardRate: '2.5%',
annualRewardRateDecimal: 0.025,
}),
}));

jest.mock('../../hooks/useBalance', () => ({
__esModule: true,
default: () => ({
stakedBalanceWei: mockPooledStakeData.assets,
stakedBalanceFiat: MOCK_STAKED_ETH_ASSET.balanceFiat,
}),
}));

describe('UnstakeInputView', () => {
it('render matches snapshot', () => {
render(UnstakeInputView);
Expand Down Expand Up @@ -81,7 +118,7 @@ describe('UnstakeInputView', () => {

fireEvent.press(screen.getByText('25%'));

expect(screen.getByText('1.14999')).toBeTruthy();
expect(screen.getByText('1.44783')).toBeTruthy();
});
});

Expand All @@ -96,13 +133,14 @@ describe('UnstakeInputView', () => {
render(UnstakeInputView);

fireEvent.press(screen.getByText('1'));

expect(screen.getByText('Review')).toBeTruthy();
});

it('displays `Not enough ETH` when input exceeds balance', () => {
render(UnstakeInputView);

fireEvent.press(screen.getByText('6'));
fireEvent.press(screen.getByText('8'));
expect(screen.queryAllByText('Not enough ETH')).toHaveLength(2);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ import { View } from 'react-native';
import useStakingInputHandlers from '../../hooks/useStakingInput';
import styleSheet from './UnstakeInputView.styles';
import InputDisplay from '../../components/InputDisplay';
import useBalance from '../../hooks/useBalance';

const UnstakeInputView = () => {
const title = strings('stake.unstake_eth');
const navigation = useNavigation();
const { styles, theme } = useStyles(styleSheet, {});

const stakeBalance = '4599964000000000000'; //TODO: Replace with actual balance - STAKE-806
const { stakedBalanceWei } = useBalance();

const {
isEth,
Expand All @@ -40,10 +41,13 @@ const UnstakeInputView = () => {
handleAmountPress,
handleKeypadChange,
conversionRate,
} = useStakingInputHandlers(new BN(stakeBalance));
} = useStakingInputHandlers(new BN(stakedBalanceWei));

const stakeBalanceInEth = renderFromWei(stakeBalance, 5);
const stakeBalanceFiatNumber = weiToFiatNumber(stakeBalance, conversionRate);
const stakeBalanceInEth = renderFromWei(stakedBalanceWei, 5);
const stakeBalanceFiatNumber = weiToFiatNumber(
stakedBalanceWei,
conversionRate,
);

const stakedBalanceText = strings('stake.staked_balance');
const stakedBalanceValue = isEth
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { RouteProp } from '@react-navigation/native';

interface UnstakeInputViewRouteParams {
stakedBalanceWei: string;
}

export interface UnstakeInputViewProps {
route: RouteProp<{ params: UnstakeInputViewRouteParams }, 'params'>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ exports[`UnstakeInputView render matches snapshot 1`] = `
>
Staked balance
:
4.59996 ETH
5.79133 ETH
</Text>
</View>
<View
Expand Down
Loading

0 comments on commit ced542a

Please sign in to comment.