From e3cc1f574ee7bb46c55c2991aaa687795802abf0 Mon Sep 17 00:00:00 2001 From: tomasklim Date: Wed, 9 Oct 2024 15:22:55 +0200 Subject: [PATCH] feat(suite): add staking/unstaking instant amount forecasting --- .../UnstakeModal/UnstakeEthForm/Options.tsx | 5 +- .../UnstakeEthForm/UnstakeEthForm.tsx | 51 ++++++++++++++++++- .../src/hooks/wallet/useUnstakeEthForm.ts | 39 +++++++++++++- packages/suite/src/support/messages.ts | 10 ++++ .../src/utils/suite/__fixtures__/stake.ts | 27 ++++++++++ .../src/utils/suite/__tests__/stake.test.ts | 18 +++++++ packages/suite/src/utils/suite/stake.ts | 35 +++++++++++++ .../components/ApproximateEthAmount.tsx | 33 ++++++++++++ 8 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/ApproximateEthAmount.tsx diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Options.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Options.tsx index 2e5969fc1263..a414bad5cb97 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Options.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Options.tsx @@ -1,4 +1,3 @@ -import { useState } from 'react'; import styled from 'styled-components'; import { FiatValue, FormattedCryptoAmount, Translation } from 'src/components/suite'; import { Paragraph, Radio } from '@trezor/components'; @@ -61,16 +60,14 @@ const InputsWrapper = styled.div<{ $isShown: boolean }>` display: ${({ $isShown }) => ($isShown ? 'block' : 'none')}; `; -type UnstakeOptions = 'all' | 'rewards' | 'other'; - interface OptionsProps { symbol: NetworkSymbol; } export const Options = ({ symbol }: OptionsProps) => { const selectedAccount = useSelector(selectSelectedAccount); + const { unstakeOption, setUnstakeOption } = useUnstakeEthFormContext(); - const [unstakeOption, setUnstakeOption] = useState('all'); const isRewardsSelected = unstakeOption === 'rewards'; const isAllSelected = unstakeOption === 'all'; const isOtherAmountSelected = unstakeOption === 'other'; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeEthForm.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeEthForm.tsx index 3605ef6ccf2f..8b08ad57b96a 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeEthForm.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/UnstakeEthForm.tsx @@ -1,5 +1,5 @@ import styled from 'styled-components'; -import { Button, Divider, Paragraph, Tooltip, Banner } from '@trezor/components'; +import { Button, Divider, Icon, Paragraph, Tooltip, Banner } from '@trezor/components'; import { spacingsPx } from '@trezor/theme'; import { Translation } from 'src/components/suite'; import { useDevice, useSelector } from 'src/hooks/suite'; @@ -12,6 +12,7 @@ import UnstakeFees from './Fees'; import { selectValidatorsQueueData } from '@suite-common/wallet-core'; import { getAccountEverstakeStakingPool } from '@suite-common/wallet-utils'; import { useMessageSystemStaking } from 'src/hooks/suite/useMessageSystemStaking'; +import { ApproximateEthAmount } from 'src/views/wallet/staking/components/EthStakingDashboard/components/ApproximateEthAmount'; // eslint-disable-next-line local-rules/no-override-ds-component const GreyP = styled(Paragraph)` @@ -47,6 +48,19 @@ const UpToDaysWrapper = styled.div` border-top: 1px solid ${({ theme }) => theme.borderElevation2}; `; +const ApproximateEthWrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + padding: ${spacingsPx.xxs} 0 ${spacingsPx.md}; +`; + +const ApproximateEthTitleWrapper = styled.div` + display: flex; + gap: ${spacingsPx.xxs}; + align-items: center; +`; + export const UnstakeEthForm = () => { const { device, isLocked } = useDevice(); const selectedAccount = useSelector(selectSelectedAccount); @@ -59,6 +73,8 @@ export const UnstakeEthForm = () => { handleSubmit, watch, signTx, + approximatedEthAmount, + unstakeOption, } = useUnstakeEthFormContext(); const { symbol } = account; @@ -70,6 +86,7 @@ export const UnstakeEthForm = () => { const hasValues = Boolean(watch(FIAT_INPUT) || watch(CRYPTO_INPUT)); // used instead of formState.isValid, which is sometimes returning false even if there are no errors const formIsValid = Object.keys(errors).length === 0; + const isUnstakeOptionOther = unstakeOption === 'other'; const { canClaim = false, claimableAmount = '0' } = getAccountEverstakeStakingPool(selectedAccount) ?? {}; @@ -119,6 +136,38 @@ export const UnstakeEthForm = () => { }} /> + + {isUnstakeOptionOther && ( + + + + + + + + } + > + + + + + {approximatedEthAmount && ( + + )} + + )} +