From 6845b47a9866d45018db187d5ad5788c4e329d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rui=20Sim=C3=A3o?= Date: Tue, 29 Aug 2023 13:22:44 +0100 Subject: [PATCH] feat: continue --- .../escrow/use-get-account-staking-data.tsx | 8 ++- src/lib/form/schemas/staking.ts | 60 +++++++++---------- src/pages/Staking copy/index.tsx | 2 - .../components/StakingForm/StakingForm.tsx | 48 +++++++++++---- .../StakingForm/StakingTransactionDetails.tsx | 26 +------- 5 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/hooks/api/escrow/use-get-account-staking-data.tsx b/src/hooks/api/escrow/use-get-account-staking-data.tsx index 2464f5dbcd..237dd3ea1b 100644 --- a/src/hooks/api/escrow/use-get-account-staking-data.tsx +++ b/src/hooks/api/escrow/use-get-account-staking-data.tsx @@ -28,6 +28,7 @@ type AccountStakingData = { amount: MonetaryAmount; apy: Big; }; + limit: MonetaryAmount; }; const getUnlockData = (stakeEndBlock: number, currentBlockNumber: number): AccountUnlockStakingData => { @@ -48,12 +49,14 @@ const getAccountStakingData = async (accountId: AccountId): Promise => - yup.object().shape({ - [STAKING_AMOUNT_FIELD]: yup - .string() - // .when([STAKING_LOCK_TIME_AMOUNT_FIELD], { - // is: !hasStaked, - // then: yup.number().required(i18n.t('forms.please_enter_your_field', { field: 'stake' })) - // }) - // .requiredAmount('stake') - .maxAmount(params[STAKING_AMOUNT_FIELD] as MaxAmountValidationParams) - .minAmount(params[STAKING_AMOUNT_FIELD] as MinAmountValidationParams, 'transfer'), - [STAKING_LOCK_TIME_AMOUNT_FIELD]: yup - .number() - // .test('is-required', i18n.t('forms.please_enter_your_field', { field: 'lock time' }), (value) => - // hasStaked ? true : value !== undefined - // ) - // .when([], { - // is: !hasStaked, - // then: yup.number().required(i18n.t('forms.please_enter_your_field', { field: 'lock time' })) - // }) - .min( - params[STAKING_LOCK_TIME_AMOUNT_FIELD].min, - `Lock time must be greater than or equal to ${params[STAKING_LOCK_TIME_AMOUNT_FIELD].min}` - ) - .max( - params[STAKING_LOCK_TIME_AMOUNT_FIELD].max, - `Lock time must be less than or equal to ${params[STAKING_LOCK_TIME_AMOUNT_FIELD].max}` - ), +const stakingSchema = (params: StakingValidationParams, hasStaked: boolean): yup.ObjectSchema => { + let baseAmountSchema = yup + .string() + .maxAmount(params[STAKING_AMOUNT_FIELD] as MaxAmountValidationParams) + .minAmount(params[STAKING_AMOUNT_FIELD] as MinAmountValidationParams, 'transfer'); + + let baseLockTimeSchema = yup + .string() + .min( + params[STAKING_LOCK_TIME_AMOUNT_FIELD].min, + `Lock time must be greater than or equal to ${params[STAKING_LOCK_TIME_AMOUNT_FIELD].min}` + ) + .max( + params[STAKING_LOCK_TIME_AMOUNT_FIELD].max, + `Lock time must be less than or equal to ${params[STAKING_LOCK_TIME_AMOUNT_FIELD].max}` + ); + + if (!hasStaked) { + baseAmountSchema = baseAmountSchema.requiredAmount('stake'); + + baseLockTimeSchema = baseLockTimeSchema.required(i18n.t('forms.please_enter_your_field', { field: 'lock time' })); + } + + return yup.object().shape({ + [STAKING_AMOUNT_FIELD]: baseAmountSchema, + [STAKING_LOCK_TIME_AMOUNT_FIELD]: baseLockTimeSchema, [STAKING_FEE_TOKEN_FIELD]: yup.string().required() }); +}; export { STAKING_AMOUNT_FIELD, STAKING_FEE_TOKEN_FIELD, STAKING_LOCK_TIME_AMOUNT_FIELD, stakingSchema }; export type { StakingFormData, StakingValidationParams }; diff --git a/src/pages/Staking copy/index.tsx b/src/pages/Staking copy/index.tsx index 0f5bfee8cb..0e5f6e60df 100644 --- a/src/pages/Staking copy/index.tsx +++ b/src/pages/Staking copy/index.tsx @@ -275,8 +275,6 @@ const Staking = (): JSX.Element => { const extensionTime = (stakedAmountAndEndBlock?.endBlock || currentBlockNumber) + convertWeeksToBlockNumbers(lockTimeValue); - console.log(stakedAmountAndEndBlock?.endBlock, currentBlockNumber, convertWeeksToBlockNumbers(lockTimeValue)); - setBlockLockTimeExtension(extensionTime); }, [currentBlockNumber, lockTime, stakedAmountAndEndBlock]); diff --git a/src/pages/Staking/components/StakingForm/StakingForm.tsx b/src/pages/Staking/components/StakingForm/StakingForm.tsx index f406600267..0b437e80c6 100644 --- a/src/pages/Staking/components/StakingForm/StakingForm.tsx +++ b/src/pages/Staking/components/StakingForm/StakingForm.tsx @@ -1,10 +1,11 @@ import { newMonetaryAmount } from '@interlay/interbtc-api'; import { mergeProps } from '@react-aria/utils'; +import { isPast } from 'date-fns'; import { ChangeEvent, useCallback, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { convertMonetaryAmountToValueInUSD, newSafeMonetaryAmount } from '@/common/utils/utils'; -import { Card, CardProps, Divider, Flex, H1, TokenInput } from '@/component-library'; +import { Alert, Card, CardProps, Divider, Flex, H1, TokenInput } from '@/component-library'; import { AuthCTA, TransactionDetails, @@ -29,6 +30,7 @@ import { stakingSchema, useForm } from '@/lib/form'; +import { pickSmallerAmount } from '@/utils/helpers/currencies'; import { getTokenInputProps } from '@/utils/helpers/input'; import { getTokenPrice } from '@/utils/helpers/prices'; import { convertBlockNumbersToWeeks, convertWeeksToBlockNumbers } from '@/utils/helpers/staking'; @@ -60,8 +62,11 @@ const StakingForm = ({ accountData, networkData, onStaking, ...props }: StakingF } }); - const inputBalance = getAvailableBalance(GOVERNANCE_TOKEN.ticker); + const isWithdrawReady = useMemo(() => !!accountData && isPast(accountData?.unlock.date), [accountData]); + const governanceBalance = getAvailableBalance(GOVERNANCE_TOKEN.ticker); + const inputBalance = + accountData?.limit && governanceBalance && pickSmallerAmount(governanceBalance, accountData.limit); const minAmount = newMonetaryAmount(1, GOVERNANCE_TOKEN); const inputSchemaParams = { @@ -72,7 +77,7 @@ const StakingForm = ({ accountData, networkData, onStaking, ...props }: StakingF const getTransactionArgs = useCallback( async (values: StakingFormData) => { const amount = newMonetaryAmount(values[STAKING_AMOUNT_FIELD] || 0, GOVERNANCE_TOKEN, true); - const lockTime = values[STAKING_LOCK_TIME_AMOUNT_FIELD]; + const lockTime = Number(values[STAKING_LOCK_TIME_AMOUNT_FIELD] || 0); const hasAmount = !amount.isZero(); const hasLockTime = lockTime && lockTime > 0; @@ -82,7 +87,7 @@ const StakingForm = ({ accountData, networkData, onStaking, ...props }: StakingF const unlockHeight = accountData.endBlock + newLockBlockNumber; - if (hasAmount && lockTime && lockTime > 0) { + if (hasAmount && hasLockTime) { return { transactionType: Transaction.ESCROW_INCREASE_LOOKED_TIME_AND_AMOUNT as const, amount, unlockHeight }; } else if (hasAmount && !hasLockTime) { // transactionType = Transaction.ESCROW_INCREASE_LOCKED_AMOUNT; @@ -131,15 +136,20 @@ const StakingForm = ({ accountData, networkData, onStaking, ...props }: StakingF const form = useForm({ initialValues: { [STAKING_AMOUNT_FIELD]: '', - [STAKING_LOCK_TIME_AMOUNT_FIELD]: 1, + [STAKING_LOCK_TIME_AMOUNT_FIELD]: '', [STAKING_FEE_TOKEN_FIELD]: transaction.fee.defaultCurrency.ticker }, - validationSchema: stakingSchema({ - [STAKING_AMOUNT_FIELD]: inputSchemaParams, - [STAKING_LOCK_TIME_AMOUNT_FIELD]: { min: STAKE_LOCK_TIME.MIN, max: maxLockTime } - }), + validationSchema: stakingSchema( + { + [STAKING_AMOUNT_FIELD]: inputSchemaParams, + [STAKING_LOCK_TIME_AMOUNT_FIELD]: { min: accountData ? 0 : STAKE_LOCK_TIME.MIN, max: maxLockTime } + }, + !!accountData + ), onSubmit: handleSubmit, onComplete: async (values) => { + if (isWithdrawReady) return; + const data = await getTransactionArgs(values); if (!data) return; @@ -166,22 +176,30 @@ const StakingForm = ({ accountData, networkData, onStaking, ...props }: StakingF const handleListSelectionChange = (value: number) => { form.setFieldValue(STAKING_LOCK_TIME_AMOUNT_FIELD, value, true); + if (isWithdrawReady) return; + const monetaryAmount = newSafeMonetaryAmount(form.values[STAKING_AMOUNT_FIELD] || 0, GOVERNANCE_TOKEN, true); mutateEstimation({ amount: monetaryAmount, lockTime: value }); }; const handleChangeAmount = (e: ChangeEvent) => { + if (isWithdrawReady) return; + const amount = e.target.value; if (!amount) return; + const lockTime = form.values[STAKING_LOCK_TIME_AMOUNT_FIELD]; + const monetaryAmount = newSafeMonetaryAmount(amount, GOVERNANCE_TOKEN, true); - mutateEstimation({ amount: monetaryAmount, lockTime: form.values[STAKING_LOCK_TIME_AMOUNT_FIELD] }); + mutateEstimation({ amount: monetaryAmount, lockTime: lockTime ? Number(lockTime) : undefined }); }; const handleChangeLockTime = (e: ChangeEvent) => { + if (isWithdrawReady) return; + const lockTime = e.target.value; if (!lockTime) return; @@ -196,11 +214,10 @@ const StakingForm = ({ accountData, networkData, onStaking, ...props }: StakingF ? convertMonetaryAmountToValueInUSD(monetaryAmount, getTokenPrice(prices, monetaryAmount.currency.ticker)?.usd) || 0 : 0; - console.log(form.errors); + const isBtnDisabled = isWithdrawReady && isTransactionFormDisabled(form, transaction.fee); - const isBtnDisabled = isTransactionFormDisabled(form, transaction.fee); + const shouldDisplayWithdrawAlert = isWithdrawReady && form.dirty; - // TODO: lock form when user needs to withdraw staked INTR return (

@@ -239,6 +256,11 @@ const StakingForm = ({ accountData, networkData, onStaking, ...props }: StakingF })} onListSelectionChange={handleListSelectionChange} /> + {shouldDisplayWithdrawAlert && ( + + Your staked {GOVERNANCE_TOKEN.ticker} needs to be withdrawn before any further actions + + )} ; - lockTime?: number; + lockTime?: string; }; type InheritAttrs = Omit; @@ -37,7 +37,7 @@ const StakingTransactionDetails = ({ const unlockDateTerm = accountData ? 'New unlock date' : 'Unlock date'; const newDate = add(accountData?.unlock.date || new Date(), { - weeks: lockTime + weeks: lockTime ? Number(lockTime) : undefined }); const unlockDateLabel = format(newDate, YEAR_MONTH_DAY_PATTERN); @@ -50,28 +50,6 @@ const StakingTransactionDetails = ({ const votingBalanceGained = accountData ? newTotalStaked.sub(accountData?.votingBalance) : newTotalStaked; - // const extendingLockTime = parseInt(lockTime); // Weeks - - // let newLockTime: number; - // let newLockingAmount: GovernanceTokenMonetaryAmount; - // if (remainingBlockNumbersToUnstake === null) { - // // If the user has not staked - // newLockTime = extendingLockTime; - // newLockingAmount = monetaryLockingAmount; - // } else { - // // If the user has staked - // const currentLockTime = convertBlockNumbersToWeeks(remainingBlockNumbersToUnstake); // Weeks - - // // New lock-time that is applied to the entire staked governance token - // newLockTime = currentLockTime + extendingLockTime; // Weeks - - // // New total staked governance token - // newLockingAmount = monetaryLockingAmount.add(stakedAmount); - // } - - // // Multiplying the new total staked governance token with the staking time divided by the maximum lock time - // return newLockingAmount.mul(newLockTime).div(STAKE_LOCK_TIME.MAX); - return (