diff --git a/projects/ui/src/components/Common/Form/FormTxn/AddPlantTxnToggle.tsx b/projects/ui/src/components/Common/Form/FormTxn/AddPlantTxnToggle.tsx index d04e68a99a..6ffaea2189 100644 --- a/projects/ui/src/components/Common/Form/FormTxn/AddPlantTxnToggle.tsx +++ b/projects/ui/src/components/Common/Form/FormTxn/AddPlantTxnToggle.tsx @@ -23,8 +23,9 @@ import useToggle from '~/hooks/display/useToggle'; import useFarmerFormTxnsSummary from '~/hooks/farmer/form-txn/useFarmerFormTxnsSummary'; import MergeIcon from '~/img/misc/merge-icon.svg'; -import { FormTxnsFormState } from '..'; +import { FormTxnsFormState } from '~/components/Common/Form'; import { FormTxn } from '~/lib/Txn'; +import SiloVestingWarningAlert from '~/components/Silo/SiloVestingWarningAlert'; const sx = { accordion: { @@ -74,18 +75,14 @@ const AddPlantTxnToggle: React.FC<{}> = () => { /// Handlers const handleToggleOn = useCallback(() => { - if (isPlant) { - setFieldValue('farmActions.primary', [FormTxn.PLANT]); - show(); - } - }, [isPlant, setFieldValue, show]); + setFieldValue('farmActions.primary', [FormTxn.PLANT]); + show(); + }, [setFieldValue, show]); const handleToggleOff = useCallback(() => { - if (isPlant) { - setFieldValue('farmActions.primary', []); - hide(); - } - }, [hide, isPlant, setFieldValue]); + setFieldValue('farmActions.primary', []); + hide(); + }, [hide, setFieldValue]); /// Effects /// Update the local state if the Form State is updated externally @@ -101,88 +98,93 @@ const AddPlantTxnToggle: React.FC<{}> = () => { if (!isPlant || !plantEnabled) return null; return ( - - - - e.stopPropagation()} - > - merge + + + + + e.stopPropagation()} + > + merge + + + Use Earned Beans + + + Toggle to claim Earned Beans in your transaction + + + + { + e.stopPropagation(); + open ? handleToggleOff() : handleToggleOn(); + }} + color="primary" /> - - - Use Earned Beans - - - Toggle to claim Earned Beans in your transaction - - - { - e.stopPropagation(); - open ? handleToggleOff() : handleToggleOn(); + + + - - - - - - - You will Plant to claim these silo rewards - - - {items.map((item, i) => ( - - - - - + > + + + You will Plant to claim these silo rewards + + + {items.map((item, i) => ( + + + + + + + {displayFullBN(item.amount, 2)} + + - {displayFullBN(item.amount, 2)} + {item.description} - - - {item.description} - - - - - ))} - - - - - + + + + ))} + + + + + + ); }; diff --git a/projects/ui/src/components/Common/Form/FormTxn/AdditionalTxnsAccordion.tsx b/projects/ui/src/components/Common/Form/FormTxn/AdditionalTxnsAccordion.tsx index 11908a325d..187fe5d526 100644 --- a/projects/ui/src/components/Common/Form/FormTxn/AdditionalTxnsAccordion.tsx +++ b/projects/ui/src/components/Common/Form/FormTxn/AdditionalTxnsAccordion.tsx @@ -4,15 +4,17 @@ import { useFormikContext } from 'formik'; import AddIcon from '@mui/icons-material/Add'; import BigNumber from 'bignumber.js'; import { ethers } from 'ethers'; -import Row from '../../Row'; +import Row from '~/components/Common/Row'; import SelectionAccordion from '~/components/Common/Accordion/SelectionAccordion'; -import { FormTxnsFormState } from '..'; +import { FormTxnsFormState } from '~/components/Common/Form'; import useToggle from '~/hooks/display/useToggle'; import useTimedRefresh from '~/hooks/app/useTimedRefresh'; -import FormTxnOptionCard from '../FormTxnOptionCard'; +import FormTxnOptionCard from '~/components/Common/Form/FormTxnOptionCard'; import useFarmerFormTxnSummary from '~/hooks/farmer/form-txn/useFarmerFormTxnsSummary'; import useFormTxnContext from '~/hooks/sdk/useFormTxnContext'; +import SiloVestingWarningAlert from '~/components/Silo/SiloVestingWarningAlert'; + import { FormTxn, FormTxnBundler } from '~/lib/Txn'; type Props = { @@ -174,44 +176,47 @@ const AdditionalTxnsAccordion: React.FC = ({ filter }) => { if (!allOptions?.length) return null; return ( - - open={open} - onChange={open ? hide : show} - title={ - - - - Add additional transactions to save gas - - - } - subtitle={ - - Claim All - + + + open={open} + onChange={open ? hide : show} + title={ + + + + Add additional transactions to save gas + + + } + subtitle={ + + Claim All + + + } + options={allOptions} + selected={local} + onToggle={handleOnToggle} + render={(item, selected) => ( + handleMouseOver(item)} + onMouseLeave={handleMouseLeave} /> - - } - options={allOptions} - selected={local} - onToggle={handleOnToggle} - render={(item, selected) => ( - handleMouseOver(item)} - onMouseLeave={handleMouseLeave} - /> - )} - /> + )} + /> + ); }; diff --git a/projects/ui/src/components/Common/Form/FormTxn/ClaimBeanDrawerToggle.tsx b/projects/ui/src/components/Common/Form/FormTxn/ClaimBeanDrawerToggle.tsx index 98e457877f..2c14ace0a8 100644 --- a/projects/ui/src/components/Common/Form/FormTxn/ClaimBeanDrawerToggle.tsx +++ b/projects/ui/src/components/Common/Form/FormTxn/ClaimBeanDrawerToggle.tsx @@ -11,8 +11,6 @@ import podIconGreen from '~/img/beanstalk/pod-icon-green.svg'; import sproutsIconGrey from '~/img/beanstalk/sprout-icon-grey.svg'; import sproutsIconGreen from '~/img/beanstalk/rinsable-sprout-icon.svg'; -import beanIconGreen from '~/img/tokens/bean-logo-circled.svg'; -import beanIconGrey from '~/img/tokens/bean-logo-circled-grey.svg'; import IconWrapper from '~/components/Common/IconWrapper'; import Centered from '~/components/Common/ZeroState/Centered'; import useFarmerFormTxnsSummary, { @@ -35,10 +33,6 @@ const actionsToIconMap = { selected: podIconGreen, grey: podIconGrey, }, - [FormTxn.CLAIM]: { - selected: beanIconGreen, - grey: beanIconGrey, - }, }; const ClaimBeanDrawerToggle: React.FC<{}> = () => { diff --git a/projects/ui/src/components/Silo/Actions/Withdraw.tsx b/projects/ui/src/components/Silo/Actions/Withdraw.tsx index 21c4c19f9c..235066deac 100644 --- a/projects/ui/src/components/Silo/Actions/Withdraw.tsx +++ b/projects/ui/src/components/Silo/Actions/Withdraw.tsx @@ -9,6 +9,7 @@ import { TokenSiloBalance, TokenValue, BeanstalkSDK, + FarmToMode, } from '@beanstalk/sdk'; import { SEEDS, STALK } from '~/constants/tokens'; import { @@ -31,7 +32,6 @@ import { FC } from '~/types'; import useFormMiddleware from '~/hooks/ledger/useFormMiddleware'; import useSdk, { getNewToOldToken } from '~/hooks/sdk'; import TokenOutput from '~/components/Common/Form/TokenOutput'; -import WarningAlert from '~/components/Common/Alert/WarningAlert'; import TxnAccordion from '~/components/Common/TxnAccordion'; import useAccount from '~/hooks/ledger/useAccount'; import AdditionalTxnsAccordion from '~/components/Common/Form/FormTxn/AdditionalTxnsAccordion'; @@ -41,6 +41,7 @@ import useFarmerSiloBalancesAsync from '~/hooks/farmer/useFarmerSiloBalancesAsyn import FormTxnProvider from '~/components/Common/Form/FormTxnProvider'; import useFormTxnContext from '~/hooks/sdk/useFormTxnContext'; import { FormTxn, PlantAndDoX, WithdrawFarmStep } from '~/lib/Txn'; +import FarmModeField from '~/components/Common/Form/FarmModeField'; // ----------------------------------------------------------------------- @@ -48,7 +49,12 @@ import { FormTxn, PlantAndDoX, WithdrawFarmStep } from '~/lib/Txn'; /// remove me when we migrate everything to TokenValue & DecimalBigNumber const toBN = tokenValueToBN; -type WithdrawFormValues = FormStateNew & FormTxnsFormState; +type WithdrawFormValues = FormStateNew & + FormTxnsFormState & { + settings: { + destination: FarmToMode; + }; + }; const WithdrawForm: FC< FormikProps & { @@ -138,6 +144,8 @@ const WithdrawForm: FC< balanceLabel="Deposited Balance" InputProps={InputProps} /> + {/** Setting: Destination */} + {isReady ? ( @@ -175,10 +183,6 @@ const WithdrawForm: FC< amount={withdrawResult.seeds.mul(-1)} /> - - You can Claim your Withdrawn assets at the start of the next - Season. - @@ -261,6 +265,9 @@ const WithdrawPropProvider: FC<{ secondary: undefined, implied: [FormTxn.MOW], }, + settings: { + destination: FarmToMode.INTERNAL, + }, }), [sdk.tokens.BEAN, token] ); @@ -280,6 +287,7 @@ const WithdrawPropProvider: FC<{ const formData = values.tokens[0]; const primaryActions = values.farmActions.primary; + const destination = values.settings.destination; const addPlant = primaryActions?.includes(FormTxn.PLANT) && @@ -292,6 +300,9 @@ const WithdrawPropProvider: FC<{ : baseAmount; if (totalAmount.lte(0)) throw new Error('Invalid amount.'); + if (!destination) { + throw new Error("Missing 'Destination' setting."); + } const withdrawTxn = new WithdrawFarmStep(sdk, token, [ ...farmerBalances.deposited.crates, diff --git a/projects/ui/src/components/Silo/Actions/index.tsx b/projects/ui/src/components/Silo/Actions/index.tsx index edfb8cc106..2899f5175f 100644 --- a/projects/ui/src/components/Silo/Actions/index.tsx +++ b/projects/ui/src/components/Silo/Actions/index.tsx @@ -26,7 +26,7 @@ import Convert from './Convert'; * up by tabs. Each tab contains a single form. * (2) a table of Deposits and Withdrawals, shown dependent on the * selected tab. The Withdrawals table also displays an aggregated - * "claimable" row and is shown for both Withdraw & Claim tabs. + * "claimable" row and is shown for the Claim tab only (updated for Silo V3) */ const SLUGS = ['deposit', 'convert', 'transfer', 'withdraw', 'claim']; @@ -52,6 +52,9 @@ const SiloActions: FC<{ return null; } + /// TODO: TEMPORARY. FIX ME + const hasClaimableBeans = true; + return ( <> @@ -60,11 +63,12 @@ const SiloActions: FC<{ - + {hasClaimableBeans && ( + + )} {tab === 0 && } - {/* {tab === 0 && token && } */} {tab === 1 && } {tab === 2 && ( @@ -72,14 +76,17 @@ const SiloActions: FC<{ {tab === 3 && ( )} - {tab === 4 && } + + {hasClaimableBeans && tab === 4 && ( + + )} {/* Tables */} - + - = 3 ? 'block' : 'none' }}> + = 4 ? 'block' : 'none' }}> diff --git a/projects/ui/src/components/Silo/SiloVestingWarningAlert.tsx b/projects/ui/src/components/Silo/SiloVestingWarningAlert.tsx new file mode 100644 index 0000000000..dbcd2fc13b --- /dev/null +++ b/projects/ui/src/components/Silo/SiloVestingWarningAlert.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import useFarmerSiloVesting from '~/hooks/farmer/useFarmerSiloVesting'; +import { displayFullBN } from '~/util'; +import WarningAlert from '../Common/Alert/WarningAlert'; + +const SiloVestingWarningAlert: React.FC<{ hide?: boolean }> = ({ + hide = false, +}) => { + const { amount, isVesting, remainingBlocks } = useFarmerSiloVesting(); + + if (!isVesting || hide) return null; + + return ( + + {`${ + amount.gte(1) ? displayFullBN(amount, 0) : '<1' + } BEANs are vesting and will be available for plant in ${remainingBlocks} blocks`} + + ); +}; + +export default SiloVestingWarningAlert; diff --git a/projects/ui/src/hooks/farmer/form-txn/useFarmerFormTxnActions.ts b/projects/ui/src/hooks/farmer/form-txn/useFarmerFormTxnActions.ts index de2ce71694..3e5ed0594c 100644 --- a/projects/ui/src/hooks/farmer/form-txn/useFarmerFormTxnActions.ts +++ b/projects/ui/src/hooks/farmer/form-txn/useFarmerFormTxnActions.ts @@ -11,9 +11,7 @@ import useAccount from '~/hooks/ledger/useAccount'; import { FormTxn } from '~/lib/Txn'; const isClaimingBeansAction = (action: FormTxn) => - action === FormTxn.CLAIM || - action === FormTxn.HARVEST || - action === FormTxn.RINSE; + action === FormTxn.HARVEST || action === FormTxn.RINSE; export default function useFarmerFormTxnsActions(options?: { showGraphicOnClaim?: boolean | undefined; diff --git a/projects/ui/src/hooks/farmer/useFarmerSiloVesting.ts b/projects/ui/src/hooks/farmer/useFarmerSiloVesting.ts new file mode 100644 index 0000000000..002495ac21 --- /dev/null +++ b/projects/ui/src/hooks/farmer/useFarmerSiloVesting.ts @@ -0,0 +1,27 @@ +import BigNumber from 'bignumber.js'; +import { useMemo } from 'react'; +import { ZERO_BN } from '~/constants'; +import { useAppSelector } from '~/state'; + +export const MAX_SILO_VESTING_BLOCKS = new BigNumber(10); + +export default function useFarmerSiloVesting() { + const morning = useAppSelector((s) => s._beanstalk.sun.morning); + + /// TODO: Fix me with the new earned beans amount + const earnedBeans = useAppSelector((s) => s._farmer.silo.beans.earned); + + return useMemo(() => { + const isVesting = morning.isMorning && morning.index.lte(10); + + const remainingBlocks = isVesting + ? MAX_SILO_VESTING_BLOCKS.minus(morning.index).plus(1) + : ZERO_BN; + + return { + amount: earnedBeans, + isVesting, + remainingBlocks, + }; + }, [earnedBeans, morning.index, morning.isMorning]); +} diff --git a/projects/ui/src/lib/Txn/FormTxn/presets.ts b/projects/ui/src/lib/Txn/FormTxn/presets.ts index 7660cf1e1a..a6c9dbcbc3 100644 --- a/projects/ui/src/lib/Txn/FormTxn/presets.ts +++ b/projects/ui/src/lib/Txn/FormTxn/presets.ts @@ -7,32 +7,20 @@ export const FormTxnBundlerPresets: { }; } = { claim: { - primary: [FormTxn.RINSE, FormTxn.HARVEST, FormTxn.CLAIM], + primary: [FormTxn.RINSE, FormTxn.HARVEST], secondary: [FormTxn.MOW, FormTxn.PLANT, FormTxn.ENROOT], }, enroot: { primary: [FormTxn.ENROOT], - secondary: [ - FormTxn.MOW, - FormTxn.PLANT, - FormTxn.RINSE, - FormTxn.HARVEST, - FormTxn.CLAIM, - ], + secondary: [FormTxn.MOW, FormTxn.PLANT, FormTxn.RINSE, FormTxn.HARVEST], }, rinseHarvest: { primary: [FormTxn.RINSE, FormTxn.HARVEST], - secondary: [FormTxn.MOW, FormTxn.PLANT, FormTxn.ENROOT, FormTxn.CLAIM], + secondary: [FormTxn.MOW, FormTxn.PLANT, FormTxn.ENROOT], }, plant: { primary: [FormTxn.PLANT], - secondary: [ - FormTxn.MOW, - FormTxn.ENROOT, - FormTxn.RINSE, - FormTxn.HARVEST, - FormTxn.CLAIM, - ], + secondary: [FormTxn.MOW, FormTxn.ENROOT, FormTxn.RINSE, FormTxn.HARVEST], }, noPrimary: { primary: [], @@ -42,7 +30,6 @@ export const FormTxnBundlerPresets: { FormTxn.ENROOT, FormTxn.RINSE, FormTxn.HARVEST, - FormTxn.CLAIM, ], }, };