diff --git a/app/components/UI/Navbar/index.js b/app/components/UI/Navbar/index.js
index aeda7315f1d..07f352786e0 100644
--- a/app/components/UI/Navbar/index.js
+++ b/app/components/UI/Navbar/index.js
@@ -52,7 +52,6 @@ import Icon, {
IconColor,
} from '../../../component-library/components/Icons/Icon';
import { AddContactViewSelectorsIDs } from '../../../../e2e/selectors/Settings/Contacts/AddContactView.selectors';
-import { ImportTokenViewSelectorsIDs } from '../../../../e2e/selectors/wallet/ImportTokenView.selectors';
const trackEvent = (event, params = {}) => {
MetaMetrics.getInstance().trackEvent(event, params);
@@ -1849,6 +1848,9 @@ export function getStakingNavbar(title, navigation, themeColors, options) {
fontSize: 14,
...fontStyles.normal,
},
+ headerTitle: {
+ alignItems: 'center',
+ },
});
function navigationPop() {
@@ -1857,7 +1859,9 @@ export function getStakingNavbar(title, navigation, themeColors, options) {
return {
headerTitle: () => (
- {title}
+
+ {title}
+
),
headerStyle: innerStyles.headerStyle,
headerLeft: () =>
@@ -1868,7 +1872,9 @@ export function getStakingNavbar(title, navigation, themeColors, options) {
onPress={navigationPop}
style={innerStyles.headerLeft}
/>
- ) : null,
+ ) : (
+ <>>
+ ),
headerRight: () =>
hasCancelButton ? (
- ) : null,
+ ) : (
+ <>>
+ ),
};
}
diff --git a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.test.tsx b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.test.tsx
index 90639128471..c7c3005ad89 100644
--- a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.test.tsx
+++ b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.test.tsx
@@ -4,11 +4,11 @@ import StakeInputView from './StakeInputView';
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';
import { ChainId, PooledStakingContract } from '@metamask/stake-sdk';
import { Contract } from 'ethers';
import { MOCK_GET_VAULT_RESPONSE } from '../../__mocks__/mockData';
+import { toWei } from '../../../../../util/number';
function render(Component: React.ComponentType) {
return renderScreen(
@@ -54,7 +54,7 @@ jest.mock('../../../../../selectors/currencyRateController.ts', () => ({
selectCurrentCurrency: jest.fn(() => 'USD'),
}));
-const mockBalanceBN = new BN('1500000000000000000');
+const mockBalanceBN = toWei('1.5'); // 1.5 ETH
const mockPooledStakingContractService: PooledStakingContract = {
chainId: ChainId.ETHEREUM,
@@ -84,12 +84,25 @@ jest.mock('../../hooks/useStakeContext.ts', () => ({
jest.mock('../../hooks/useBalance', () => ({
__esModule: true,
default: () => ({
- balance: '1.5',
+ balanceETH: '1.5',
balanceWei: mockBalanceBN,
balanceFiatNumber: '3000',
}),
}));
+const mockGasFee = toWei('0.0001');
+
+jest.mock('../../hooks/useStakingGasFee', () => ({
+ __esModule: true,
+ default: () => ({
+ estimatedGasFeeWei: mockGasFee,
+ gasLimit: 70122,
+ isLoadingStakingGasFee: false,
+ isStakingGasFeeError: false,
+ refreshGasValues: jest.fn(),
+ }),
+}));
+
const mockVaultData = MOCK_GET_VAULT_RESPONSE;
// Mock hooks
diff --git a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
index 9351d57b785..9dd1fdfaff5 100644
--- a/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
+++ b/app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx
@@ -17,14 +17,12 @@ import EstimatedAnnualRewardsCard from '../../components/EstimatedAnnualRewardsC
import Routes from '../../../../../constants/navigation/Routes';
import styleSheet from './StakeInputView.styles';
import useStakingInputHandlers from '../../hooks/useStakingInput';
-import useBalance from '../../hooks/useBalance';
import InputDisplay from '../../components/InputDisplay';
const StakeInputView = () => {
const title = strings('stake.stake_eth');
const navigation = useNavigation();
const { styles, theme } = useStyles(styleSheet, {});
- const { balance, balanceFiatNumber, balanceWei } = useBalance();
const {
isEth,
@@ -45,7 +43,9 @@ const StakeInputView = () => {
annualRewardsFiat,
annualRewardRate,
isLoadingVaultData,
- } = useStakingInputHandlers(balanceWei);
+ handleMax,
+ balanceValue,
+ } = useStakingInputHandlers();
const navigateToLearnMoreModal = () => {
navigation.navigate('StakeModals', {
@@ -73,6 +73,15 @@ const StakeInputView = () => {
annualRewardRate,
]);
+ const handleMaxButtonPress = () => {
+ navigation.navigate('StakeModals', {
+ screen: Routes.STAKING.MODALS.MAX_INPUT,
+ params: {
+ handleMaxPress: handleMax,
+ },
+ });
+ };
+
const balanceText = strings('stake.balance');
const buttonLabel = !isNonZeroAmount
@@ -81,10 +90,6 @@ const StakeInputView = () => {
? strings('stake.not_enough_eth')
: strings('stake.review');
- const balanceValue = isEth
- ? `${balance} ETH`
- : `${balanceFiatNumber?.toString()} ${currentCurrency.toUpperCase()}`;
-
useEffect(() => {
navigation.setOptions(
getStakingNavbar(title, navigation, theme.colors, {
@@ -121,6 +126,7 @@ const StakeInputView = () => {
+
-
- Stake ETH
-
+
+ Stake ETH
+
+
({
default: () => ({
stakedBalanceWei: mockPooledStakeData.assets,
stakedBalanceFiat: MOCK_STAKED_ETH_ASSET.balanceFiat,
+ formattedStakedBalanceETH: '5.79133 ETH',
}),
}));
diff --git a/app/components/UI/Stake/Views/UnstakeInputView/UnstakeInputView.tsx b/app/components/UI/Stake/Views/UnstakeInputView/UnstakeInputView.tsx
index ddfa676d158..269151a431b 100644
--- a/app/components/UI/Stake/Views/UnstakeInputView/UnstakeInputView.tsx
+++ b/app/components/UI/Stake/Views/UnstakeInputView/UnstakeInputView.tsx
@@ -1,6 +1,5 @@
import { useNavigation } from '@react-navigation/native';
import React, { useCallback, useEffect } from 'react';
-import { BN } from 'ethereumjs-util';
import UnstakeInputViewBanner from './UnstakeBanner';
import { strings } from '../../../../../../locales/i18n';
import Button, {
@@ -9,26 +8,22 @@ import Button, {
ButtonWidthTypes,
} from '../../../../../component-library/components/Buttons/Button';
import { TextVariant } from '../../../../../component-library/components/Texts/Text';
-import { renderFromWei, weiToFiatNumber } from '../../../../../util/number';
import Keypad from '../../../../Base/Keypad';
import { useStyles } from '../../../../hooks/useStyles';
import { getStakingNavbar } from '../../../Navbar';
import ScreenLayout from '../../../Ramp/components/ScreenLayout';
import QuickAmounts from '../../components/QuickAmounts';
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';
import Routes from '../../../../../constants/navigation/Routes';
+import useUnstakingInputHandlers from '../../hooks/useUnstakingInput';
const UnstakeInputView = () => {
const title = strings('stake.unstake_eth');
const navigation = useNavigation();
const { styles, theme } = useStyles(styleSheet, {});
- const { stakedBalanceWei } = useBalance();
-
const {
isEth,
currentCurrency,
@@ -42,19 +37,10 @@ const UnstakeInputView = () => {
percentageOptions,
handleAmountPress,
handleKeypadChange,
- conversionRate,
- } = useStakingInputHandlers(new BN(stakedBalanceWei));
-
- const stakeBalanceInEth = renderFromWei(stakedBalanceWei, 5);
- const stakeBalanceFiatNumber = weiToFiatNumber(
- stakedBalanceWei,
- conversionRate,
- );
+ stakedBalanceValue,
+ } = useUnstakingInputHandlers();
const stakedBalanceText = strings('stake.staked_balance');
- const stakedBalanceValue = isEth
- ? `${stakeBalanceInEth} ETH`
- : `${stakeBalanceFiatNumber?.toString()} ${currentCurrency.toUpperCase()}`;
const buttonLabel = !isNonZeroAmount
? strings('stake.enter_amount')
diff --git a/app/components/UI/Stake/Views/UnstakeInputView/__snapshots__/UnstakeInputView.test.tsx.snap b/app/components/UI/Stake/Views/UnstakeInputView/__snapshots__/UnstakeInputView.test.tsx.snap
index 0e1816f6621..263d1be6b4e 100644
--- a/app/components/UI/Stake/Views/UnstakeInputView/__snapshots__/UnstakeInputView.test.tsx.snap
+++ b/app/components/UI/Stake/Views/UnstakeInputView/__snapshots__/UnstakeInputView.test.tsx.snap
@@ -102,26 +102,49 @@ exports[`UnstakeInputView render matches snapshot 1`] = `
pointerEvents="box-none"
style={
{
- "marginHorizontal": 16,
+ "alignItems": "flex-start",
+ "bottom": 0,
+ "justifyContent": "center",
+ "left": 0,
+ "opacity": 1,
+ "position": "absolute",
+ "top": 0,
+ }
+ }
+ />
+
-
- Unstake ETH
-
+
+ Unstake ETH
+
+
+ StyleSheet.create({
+ container: {
+ paddingHorizontal: 16,
+ },
+ textContainer: {
+ paddingBottom: 16,
+ paddingRight: 16,
+ },
+ buttonContainer: {
+ flexDirection: 'row',
+ gap: 16,
+ paddingHorizontal: 16,
+ paddingBottom: 16,
+ },
+ button: {
+ flex: 1,
+ },
+ });
+
+export default createMaxInputModalStyles;
diff --git a/app/components/UI/Stake/components/MaxInputModal/MaxInputModal.test.tsx b/app/components/UI/Stake/components/MaxInputModal/MaxInputModal.test.tsx
new file mode 100644
index 00000000000..8092f9d9fc5
--- /dev/null
+++ b/app/components/UI/Stake/components/MaxInputModal/MaxInputModal.test.tsx
@@ -0,0 +1,67 @@
+import { renderScreen } from '../../../../../util/test/renderWithProvider';
+import MaxInputModal from '.';
+import { fireEvent } from '@testing-library/react-native';
+import Routes from '../../../../../constants/navigation/Routes';
+
+const mockNavigate = jest.fn();
+const mockGoBack = jest.fn();
+const mockHandleMaxPress = jest.fn();
+
+jest.mock('@react-navigation/native', () => {
+ const actualReactNavigation = jest.requireActual('@react-navigation/native');
+ return {
+ ...actualReactNavigation,
+ useRoute: () => ({
+ params: {
+ handleMaxPress: mockHandleMaxPress,
+ },
+ }),
+ useNavigation: () => ({
+ navigate: mockNavigate,
+ goBack: mockGoBack,
+ }),
+ };
+});
+
+const renderMaxInputModal = () =>
+ renderScreen(MaxInputModal, { name: Routes.STAKING.MODALS.MAX_INPUT });
+
+describe('MaxInputModal', () => {
+ it('render matches snapshot', () => {
+ const { toJSON } = renderMaxInputModal();
+ expect(toJSON()).toMatchSnapshot();
+ });
+
+ it('calls handleMaxPress when "Use max" button is pressed', () => {
+ const { getByText } = renderMaxInputModal();
+
+ // Press the "Use Max" button
+ const useMaxButton = getByText('Use max');
+ fireEvent.press(useMaxButton);
+
+ // Check if handleMaxPress was called
+ expect(mockHandleMaxPress).toHaveBeenCalledTimes(1);
+ });
+
+ it('closes the BottomSheet when "Cancel" button is pressed', () => {
+ const { getByText } = renderMaxInputModal();
+
+ // Press the "Cancel" button
+ const cancelButton = getByText('Cancel');
+ fireEvent.press(cancelButton);
+
+ // Check if the BottomSheet's close function was called
+ expect(mockGoBack).toHaveBeenCalled();
+ });
+
+ it('closes the BottomSheet when "Use Max" button is pressed', () => {
+ const { getByText } = renderMaxInputModal();
+
+ // Press the "Use Max" button
+ const useMaxButton = getByText('Use max');
+ fireEvent.press(useMaxButton);
+
+ // Check if the BottomSheet's close function was called
+ expect(mockGoBack).toHaveBeenCalled();
+ });
+});
diff --git a/app/components/UI/Stake/components/MaxInputModal/__snapshots__/MaxInputModal.test.tsx.snap b/app/components/UI/Stake/components/MaxInputModal/__snapshots__/MaxInputModal.test.tsx.snap
new file mode 100644
index 00000000000..c3aa8b2abf5
--- /dev/null
+++ b/app/components/UI/Stake/components/MaxInputModal/__snapshots__/MaxInputModal.test.tsx.snap
@@ -0,0 +1,656 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`MaxInputModal render matches snapshot 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+ MaxInput
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Max
+
+
+
+
+
+
+
+
+
+
+
+
+ Max is the total amount of ETH you have, minus the gas fee required to stake. It’s a good idea to keep some extra ETH in your wallet for future transactions.
+
+
+
+
+
+
+
+ Cancel
+
+
+
+
+
+
+ Use max
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/app/components/UI/Stake/components/MaxInputModal/index.tsx b/app/components/UI/Stake/components/MaxInputModal/index.tsx
new file mode 100644
index 00000000000..a7534a2214c
--- /dev/null
+++ b/app/components/UI/Stake/components/MaxInputModal/index.tsx
@@ -0,0 +1,79 @@
+import React, { useRef } from 'react';
+import { View } from 'react-native';
+import BottomSheet, {
+ type BottomSheetRef,
+} from '../../../../../component-library/components/BottomSheets/BottomSheet';
+import Text, {
+ TextVariant,
+} from '../../../../../component-library/components/Texts/Text';
+import Button, {
+ ButtonSize,
+ ButtonVariants,
+ ButtonWidthTypes,
+} from '../../../../../component-library/components/Buttons/Button';
+import { strings } from '../../../../../../locales/i18n';
+import BottomSheetHeader from '../../../../../component-library/components/BottomSheets/BottomSheetHeader';
+import createMaxInputModalStyles from './MaxInputModal.styles';
+import { useRoute, RouteProp } from '@react-navigation/native';
+
+const styles = createMaxInputModalStyles();
+
+interface MaxInputModalRouteParams {
+ handleMaxPress: () => void;
+}
+
+const MaxInputModal = () => {
+ const route =
+ useRoute>();
+ const sheetRef = useRef(null);
+
+ const { handleMaxPress } = route.params;
+
+ const handleCancel = () => {
+ sheetRef.current?.onCloseBottomSheet();
+ };
+
+ const handleConfirm = () => {
+ sheetRef.current?.onCloseBottomSheet();
+ handleMaxPress();
+ };
+
+ return (
+
+
+
+
+ {strings('stake.max_modal.title')}
+
+
+
+
+ {strings('stake.max_modal.description')}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default MaxInputModal;
diff --git a/app/components/UI/Stake/components/QuickAmounts.tsx b/app/components/UI/Stake/components/QuickAmounts.tsx
index 6adc535be6f..fc089600ae4 100644
--- a/app/components/UI/Stake/components/QuickAmounts.tsx
+++ b/app/components/UI/Stake/components/QuickAmounts.tsx
@@ -39,44 +39,61 @@ const createStyles = (colors: Colors) =>
interface AmountProps {
amount: QuickAmount;
onPress: (amount: QuickAmount) => void;
-
+ onMaxPress?: () => void;
disabled?: boolean;
}
-const Amount = ({ amount, onPress }: AmountProps) => {
+const Amount = ({ amount, onPress, onMaxPress }: AmountProps) => {
const { value, label } = amount;
const { colors } = useTheme();
const styles = createStyles(colors);
+
const handlePress = useCallback(() => {
+ if (value === 1 && onMaxPress) {
+ onMaxPress();
+ return;
+ }
onPress(amount);
- }, [onPress, amount]);
+ }, [value, onMaxPress, amount, onPress]);
return (
-
+ <>
+
+ >
);
};
interface QuickAmountsProps {
amounts: QuickAmount[];
onAmountPress: (amount: QuickAmount) => void;
+ onMaxPress?: () => void;
}
-const QuickAmounts = ({ amounts, onAmountPress }: QuickAmountsProps) => {
+const QuickAmounts = ({
+ amounts,
+ onAmountPress,
+ onMaxPress,
+}: QuickAmountsProps) => {
const { colors } = useTheme();
const styles = createStyles(colors);
return (
{amounts.map((amount, index: number) => (
-
+
))}
);
diff --git a/app/components/UI/Stake/components/StakeButton/StakeButton.test.tsx b/app/components/UI/Stake/components/StakeButton/StakeButton.test.tsx
index 53d5f7cad03..bfd4eafd26b 100644
--- a/app/components/UI/Stake/components/StakeButton/StakeButton.test.tsx
+++ b/app/components/UI/Stake/components/StakeButton/StakeButton.test.tsx
@@ -53,7 +53,9 @@ jest.mock('../../hooks/useStakingEligibility', () => ({
isEligible: true,
loading: false,
error: null,
- refreshPooledStakingEligibility: jest.fn(),
+ refreshPooledStakingEligibility: jest
+ .fn()
+ .mockResolvedValueOnce({ isEligible: true }),
}),
}));
diff --git a/app/components/UI/Stake/components/StakeButton/index.tsx b/app/components/UI/Stake/components/StakeButton/index.tsx
index 7a92f67d3cb..f31695671bc 100644
--- a/app/components/UI/Stake/components/StakeButton/index.tsx
+++ b/app/components/UI/Stake/components/StakeButton/index.tsx
@@ -38,11 +38,10 @@ const StakeButtonContent = ({ asset }: StakeButtonProps) => {
const browserTabs = useSelector((state: RootState) => state.browser.tabs);
const chainId = useSelector(selectChainId);
- const { isEligible, refreshPooledStakingEligibility } =
- useStakingEligibility();
+ const { refreshPooledStakingEligibility } = useStakingEligibility();
const onStakeButtonPress = async () => {
- await refreshPooledStakingEligibility();
+ const { isEligible } = await refreshPooledStakingEligibility();
if (isPooledStakingFeatureEnabled() && isEligible) {
navigation.navigate('StakeScreens', { screen: Routes.STAKING.STAKE });
} else {
diff --git a/app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.test.tsx b/app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.test.tsx
new file mode 100644
index 00000000000..bd15a568f15
--- /dev/null
+++ b/app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.test.tsx
@@ -0,0 +1,63 @@
+import React from 'react';
+import renderWithProvider from '../../../../../../../util/test/renderWithProvider';
+import ClaimBanner from './ClaimBanner';
+import { fireEvent } from '@testing-library/react-native';
+import { createMockAccountsControllerState } from '../../../../../../../util/test/accountsControllerTestUtils';
+import { backgroundState } from '../../../../../../../util/test/initial-root-state';
+import { MOCK_POOL_STAKING_SDK } from '../../../../__mocks__/mockData';
+
+const MOCK_CLAIM_AMOUNT = '0.016';
+const MOCK_ADDRESS_1 = '0x0123456789abcdef0123456789abcdef01234567';
+
+const MOCK_ACCOUNTS_CONTROLLER_STATE = createMockAccountsControllerState([
+ MOCK_ADDRESS_1,
+]);
+
+const mockInitialState = {
+ settings: {},
+ engine: {
+ backgroundState: {
+ ...backgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
+ },
+ },
+};
+
+jest.mock('../../../../hooks/useStakeContext', () => ({
+ __esModule: true,
+ useStakeContext: jest.fn(() => MOCK_POOL_STAKING_SDK),
+}));
+
+const mockAttemptPoolStakedClaimTransaction = jest.fn();
+
+jest.mock('../../../../hooks/usePoolStakedClaim', () => ({
+ __esModule: true,
+ default: () => ({
+ attemptPoolStakedClaimTransaction: mockAttemptPoolStakedClaimTransaction,
+ }),
+}));
+
+describe('ClaimBanner', () => {
+ it('render matches snapshot', () => {
+ const { toJSON } = renderWithProvider(
+ ,
+ { state: mockInitialState },
+ );
+
+ expect(toJSON()).toMatchSnapshot();
+ });
+
+ it('claim button is disabled on subsequent presses', async () => {
+ const { getByTestId } = renderWithProvider(
+ ,
+ { state: mockInitialState },
+ );
+
+ const claimButton = getByTestId('claim-banner-claim-eth-button');
+
+ fireEvent.press(claimButton);
+
+ expect(claimButton.props.disabled).toBe(true);
+ expect(mockAttemptPoolStakedClaimTransaction).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.tsx b/app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.tsx
index 708dd7d038e..589e275325f 100644
--- a/app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.tsx
+++ b/app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useState } from 'react';
import Banner, {
BannerAlertSeverity,
BannerVariant,
@@ -27,6 +27,9 @@ type StakeBannerProps = Pick & {
const ClaimBanner = ({ claimableAmount, style }: StakeBannerProps) => {
const { styles } = useStyles(styleSheet, {});
+ const [isSubmittingClaimTransaction, setIsSubmittingClaimTransaction] =
+ useState(false);
+
const activeAccount = useSelector(selectSelectedInternalAccount);
const { attemptPoolStakedClaimTransaction } = usePoolStakedClaim();
@@ -34,22 +37,45 @@ const ClaimBanner = ({ claimableAmount, style }: StakeBannerProps) => {
const { pooledStakesData, refreshPooledStakes } = usePooledStakes();
const onClaimPress = async () => {
- if (!activeAccount?.address) return;
+ try {
+ if (!activeAccount?.address) return;
+
+ setIsSubmittingClaimTransaction(true);
+
+ const txRes = await attemptPoolStakedClaimTransaction(
+ activeAccount?.address,
+ pooledStakesData,
+ );
+
+ const transactionId = txRes?.transactionMeta.id;
- const txRes = await attemptPoolStakedClaimTransaction(
- activeAccount?.address,
- pooledStakesData,
- );
+ Engine.controllerMessenger.subscribeOnceIf(
+ 'TransactionController:transactionConfirmed',
+ () => {
+ refreshPooledStakes();
+ setIsSubmittingClaimTransaction(false);
+ },
+ (transactionMeta) => transactionMeta.id === transactionId,
+ );
- const transactionId = txRes?.transactionMeta.id;
+ Engine.controllerMessenger.subscribeOnceIf(
+ 'TransactionController:transactionFailed',
+ () => {
+ setIsSubmittingClaimTransaction(false);
+ },
+ ({ transactionMeta }) => transactionMeta.id === transactionId,
+ );
- Engine.controllerMessenger.subscribeOnceIf(
- 'TransactionController:transactionConfirmed',
- () => {
- refreshPooledStakes();
- },
- (transactionMeta) => transactionMeta.id === transactionId,
- );
+ Engine.controllerMessenger.subscribeOnceIf(
+ 'TransactionController:transactionRejected',
+ () => {
+ setIsSubmittingClaimTransaction(false);
+ },
+ ({ transactionMeta }) => transactionMeta.id === transactionId,
+ );
+ } catch (e) {
+ setIsSubmittingClaimTransaction(false);
+ }
};
return (
@@ -65,6 +91,7 @@ const ClaimBanner = ({ claimableAmount, style }: StakeBannerProps) => {
})}