allow delegation of vested tokens
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useContext, useEffect, useLayoutEffect } from 'react'
|
||||
import React, { useContext, useEffect } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { ErrorBoundary } from 'react-error-boundary'
|
||||
import { BrowserRouter as Router } from 'react-router-dom'
|
||||
@@ -15,7 +15,7 @@ import { maximizeWindow } from './utils'
|
||||
const App = () => {
|
||||
const { clientDetails } = useContext(ClientContext)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
maximizeWindow()
|
||||
}, [])
|
||||
|
||||
|
||||
@@ -12,11 +12,10 @@ import {
|
||||
} from '@mui/material'
|
||||
import { yupResolver } from '@hookform/resolvers/yup'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { EnumNodeType } from '../../types/global'
|
||||
import { NodeTypeSelector } from '../../components/NodeTypeSelector'
|
||||
import { bond, vestingBond, majorToMinor } from '../../requests'
|
||||
import { validationSchema } from './validationSchema'
|
||||
import { Gateway, MixNode, TBondArgs } from '../../types'
|
||||
import { Gateway, MixNode, TBondArgs, EnumNodeType } from '../../types'
|
||||
import { ClientContext } from '../../context/main'
|
||||
import { Fee, TokenPoolSelector } from '../../components'
|
||||
|
||||
@@ -107,7 +106,7 @@ export const BondForm = ({
|
||||
const watchNodeType = watch('nodeType', defaultValues.nodeType)
|
||||
const watchAdvancedOptions = watch('withAdvancedOptions', defaultValues.withAdvancedOptions)
|
||||
|
||||
const onSubmit = async (data: TBondFormFields, cb: (data: TBondArgs) => Promise<any>) => {
|
||||
const onSubmit = async (data: TBondFormFields, cb: (data: TBondArgs) => Promise<void>) => {
|
||||
const formattedData = formatData(data)
|
||||
const pledge = await majorToMinor(data.amount)
|
||||
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
import React, { useContext } from 'react'
|
||||
import React, { useEffect, useContext } from 'react'
|
||||
import { Box, Button, CircularProgress, FormControl, Grid, InputAdornment, TextField, Typography } from '@mui/material'
|
||||
import { yupResolver } from '@hookform/resolvers/yup'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { EnumNodeType } from '../../types'
|
||||
import { DelegationResult, EnumNodeType, TDelegateArgs } from '../../types'
|
||||
import { validationSchema } from './validationSchema'
|
||||
import { ClientContext } from '../../context/main'
|
||||
import { delegate, majorToMinor } from '../../requests'
|
||||
import { delegate, majorToMinor, vestingDelegateToMixnode } from '../../requests'
|
||||
import { checkHasEnoughFunds } from '../../utils'
|
||||
import { Fee } from '../../components'
|
||||
import { Fee, TokenPoolSelector } from '../../components'
|
||||
|
||||
type TDelegateForm = {
|
||||
nodeType: EnumNodeType
|
||||
identity: string
|
||||
amount: string
|
||||
tokenPool: string
|
||||
type: EnumNodeType
|
||||
}
|
||||
|
||||
const defaultValues: TDelegateForm = {
|
||||
nodeType: EnumNodeType.mixnode,
|
||||
identity: '',
|
||||
amount: '',
|
||||
tokenPool: 'balance',
|
||||
type: EnumNodeType.mixnode,
|
||||
}
|
||||
|
||||
export const DelegateForm = ({
|
||||
@@ -30,37 +32,36 @@ export const DelegateForm = ({
|
||||
}) => {
|
||||
const {
|
||||
register,
|
||||
watch,
|
||||
handleSubmit,
|
||||
setError,
|
||||
setValue,
|
||||
reset,
|
||||
formState: { errors, isSubmitting },
|
||||
} = useForm<TDelegateForm>({
|
||||
defaultValues,
|
||||
resolver: yupResolver(validationSchema),
|
||||
})
|
||||
|
||||
const watchNodeType = watch('nodeType', defaultValues.nodeType)
|
||||
const { userBalance, currency, clientDetails } = useContext(ClientContext)
|
||||
|
||||
const { userBalance, currency } = useContext(ClientContext)
|
||||
|
||||
const onSubmit = async (data: TDelegateForm) => {
|
||||
const hasEnoughFunds = await checkHasEnoughFunds(data.amount)
|
||||
if (!hasEnoughFunds) {
|
||||
return setError('amount', {
|
||||
message: 'Not enough funds in wallet',
|
||||
})
|
||||
}
|
||||
useEffect(() => {
|
||||
reset()
|
||||
}, [clientDetails])
|
||||
|
||||
const onSubmit = async (data: TDelegateForm, cb: (data: TDelegateArgs) => Promise<DelegationResult>) => {
|
||||
const amount = await majorToMinor(data.amount)
|
||||
|
||||
await delegate({
|
||||
type: data.nodeType,
|
||||
await cb({
|
||||
type: data.type,
|
||||
identity: data.identity,
|
||||
amount,
|
||||
})
|
||||
.then((res) => {
|
||||
.then(async (res) => {
|
||||
if (data.tokenPool === 'balance') {
|
||||
await userBalance.fetchBalance()
|
||||
} else {
|
||||
await userBalance.fetchTokenAllocation()
|
||||
}
|
||||
onSuccess({ amount: data.amount, address: res.target_address })
|
||||
userBalance.fetchBalance()
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
@@ -86,7 +87,13 @@ export const DelegateForm = ({
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
{userBalance.originalVesting && (
|
||||
<Grid item xs={6}>
|
||||
<TokenPoolSelector onSelect={(pool) => setValue('tokenPool', pool)} />
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
<Grid item xs={6}>
|
||||
<TextField
|
||||
{...register('amount')}
|
||||
required
|
||||
@@ -102,7 +109,7 @@ export const DelegateForm = ({
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid item xs={12}>
|
||||
<Fee feeType="DelegateToMixnode" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -117,7 +124,9 @@ export const DelegateForm = ({
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
onClick={handleSubmit(onSubmit)}
|
||||
onClick={handleSubmit((data) =>
|
||||
onSubmit(data, data.tokenPool === 'balance' ? delegate : vestingDelegateToMixnode),
|
||||
)}
|
||||
disabled={isSubmitting}
|
||||
data-testid="delegate-button"
|
||||
variant="contained"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as Yup from 'yup'
|
||||
import { validateAmount, validateKey } from '../../utils'
|
||||
import { checkHasEnoughFunds, checkHasEnoughLockedTokens, validateAmount, validateKey } from '../../utils'
|
||||
|
||||
export const validationSchema = Yup.object().shape({
|
||||
identity: Yup.string()
|
||||
@@ -9,7 +9,27 @@ export const validationSchema = Yup.object().shape({
|
||||
'A valid identity key is required e.g. 824WyExLUWvLE2mpSHBatN4AoByuLzfnHFeHWiBYzg4z',
|
||||
(value) => (!!value ? validateKey(value, 32) : false),
|
||||
),
|
||||
|
||||
amount: Yup.string()
|
||||
.required()
|
||||
.test('valid-amount-key', 'A valid amount is required', (value) => (!!value ? validateAmount(value, '0') : false)),
|
||||
.test('valid-amount', 'A valid amount is required', async function (value) {
|
||||
const isValid = await validateAmount(value || '', '0')
|
||||
const hasEnoughBalance = await checkHasEnoughFunds(value || '')
|
||||
const hasEnoughLocked = await checkHasEnoughLockedTokens(value || '')
|
||||
|
||||
if (!isValid) {
|
||||
return this.createError({ message: `A valid amount is required` })
|
||||
}
|
||||
|
||||
if (this.parent.tokenPool === 'balance' && !hasEnoughBalance) {
|
||||
console.log('here')
|
||||
return this.createError({ message: 'Not enough funds in wallet' })
|
||||
}
|
||||
|
||||
if (this.parent.tokenPool === 'locked' && !hasEnoughLocked) {
|
||||
return this.createError({ message: 'Not enough locked tokens' })
|
||||
}
|
||||
|
||||
return true
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -62,6 +62,12 @@ export type TBondArgs = {
|
||||
ownerSignature: string
|
||||
}
|
||||
|
||||
export type TDelegateArgs = {
|
||||
type: EnumNodeType
|
||||
identity: string
|
||||
amount: Coin
|
||||
}
|
||||
|
||||
export type TCurrency = {
|
||||
minor: 'UNYM' | 'UNYMT'
|
||||
major: 'NYM' | 'NYMT'
|
||||
|
||||
Reference in New Issue
Block a user