From 3382642d70b3e8333893acccd754b9ec8669c9f9 Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 28 Jun 2022 17:30:09 +0200 Subject: [PATCH] feat(wallet-bonding): node settings flow --- .../src/pages/bonding/bonding/BondingCard.tsx | 1 + .../components/SimpleDialog.stories.tsx | 6 ++ .../src/pages/bonding/mixnode/MixnodeCard.tsx | 2 +- .../mixnode/node-settings/NodeSettings.tsx | 85 ++++++++++++++----- .../node-settings/ProfitMarginModal.tsx | 79 +++++++++-------- .../mixnode/node-settings/SummaryModal.tsx | 47 ++++++++++ .../bonding/mixnode/node-settings/schema.ts | 9 +- 7 files changed, 171 insertions(+), 58 deletions(-) create mode 100644 nym-wallet/src/pages/bonding/mixnode/node-settings/SummaryModal.tsx diff --git a/nym-wallet/src/pages/bonding/bonding/BondingCard.tsx b/nym-wallet/src/pages/bonding/bonding/BondingCard.tsx index b13ce8bef4..9f804f1176 100644 --- a/nym-wallet/src/pages/bonding/bonding/BondingCard.tsx +++ b/nym-wallet/src/pages/bonding/bonding/BondingCard.tsx @@ -177,6 +177,7 @@ const BondingCard = () => { confirmButton="Done" maxWidth="xs" fullWidth + sx={{ textAlign: 'center' }} > View on blockchain diff --git a/nym-wallet/src/pages/bonding/components/SimpleDialog.stories.tsx b/nym-wallet/src/pages/bonding/components/SimpleDialog.stories.tsx index 8c8d860692..ff2e88ce5b 100644 --- a/nym-wallet/src/pages/bonding/components/SimpleDialog.stories.tsx +++ b/nym-wallet/src/pages/bonding/components/SimpleDialog.stories.tsx @@ -33,3 +33,9 @@ Default.args = { cancelButton: false, disabled: false, }; + +export const CenteredText = Template.bind({}); +CenteredText.args = { + ...Default.args, + sx: { textAlign: 'center' }, +}; diff --git a/nym-wallet/src/pages/bonding/mixnode/MixnodeCard.tsx b/nym-wallet/src/pages/bonding/mixnode/MixnodeCard.tsx index 7ad3590dac..197b40009f 100644 --- a/nym-wallet/src/pages/bonding/mixnode/MixnodeCard.tsx +++ b/nym-wallet/src/pages/bonding/mixnode/MixnodeCard.tsx @@ -130,7 +130,7 @@ const MixnodeCard = ({ mixnode }: { mixnode: BondedMixnode }) => { explorer - + setShowNodeSettings(false)} /> ); }; diff --git a/nym-wallet/src/pages/bonding/mixnode/node-settings/NodeSettings.tsx b/nym-wallet/src/pages/bonding/mixnode/node-settings/NodeSettings.tsx index fd8c239818..363333b797 100644 --- a/nym-wallet/src/pages/bonding/mixnode/node-settings/NodeSettings.tsx +++ b/nym-wallet/src/pages/bonding/mixnode/node-settings/NodeSettings.tsx @@ -1,35 +1,82 @@ import * as React from 'react'; -import { useState } from 'react'; -import { MajorCurrencyAmount } from '@nymproject/types'; +import { useContext, useEffect, useState } from 'react'; +import { MajorCurrencyAmount, TransactionExecuteResult } from '@nymproject/types'; +import { Link } from '@nymproject/react/link/Link'; +import { Typography } from '@mui/material'; import ProfitMarginModal from './ProfitMarginModal'; -import { BondedMixnode } from '../../../../context'; +import { AppContext, BondedMixnode, urls } from '../../../../context'; +import SummaryModal from './SummaryModal'; +import { SimpleDialog } from '../../components'; interface Props { mixnode: BondedMixnode; - open: boolean; + show: boolean; + onClose: () => void; } +// TODO fetch real estimated operator reward for 10% PM const MOCK_ESTIMATED_OP_REWARD: MajorCurrencyAmount = { amount: '42', denom: 'NYM' }; -const NodeSettings = ({ open, mixnode }: Props) => { +const NodeSettings = ({ mixnode, show, onClose }: Props) => { const [profitMargin, setProfitMargin] = useState(); - const [pmModalOpen, setPmModalOpen] = useState(true); + const [fee, setFee] = useState({ amount: '0', denom: 'NYM' }); + const [step, setStep] = useState<1 | 2 | 3>(1); + const [tx, setTx] = useState(); - if (!open) return null; + const { network } = useContext(AppContext); + + useEffect(() => { + setFee({ amount: '42', denom: 'NYM' }); // TODO fetch real fee amount + }, [profitMargin]); + + const submit = () => { + // TODO send request to update profit margin + setStep(3); // on success + // setTx(requestResult) + }; + + const reset = () => { + setProfitMargin(0); + setStep(1); + onClose(); + }; return ( - { - setPmModalOpen(false); - }} - onSubmit={async (pm) => { - setProfitMargin(pm); - setPmModalOpen(false); - }} - estimatedOpReward={MOCK_ESTIMATED_OP_REWARD} - currentPm={mixnode.profitMargin} - /> + <> + { + setProfitMargin(pm); + setStep(2); + }} + estimatedOpReward={MOCK_ESTIMATED_OP_REWARD} + currentPm={mixnode.profitMargin} + /> + setStep(1)} + currentPm={mixnode.profitMargin} + newPm={profitMargin as number} + fee={fee as MajorCurrencyAmount} + /> + + This operation can take up to one hour to process + + View on blockchain + + + ); }; diff --git a/nym-wallet/src/pages/bonding/mixnode/node-settings/ProfitMarginModal.tsx b/nym-wallet/src/pages/bonding/mixnode/node-settings/ProfitMarginModal.tsx index 120539ca5a..73887c64a6 100644 --- a/nym-wallet/src/pages/bonding/mixnode/node-settings/ProfitMarginModal.tsx +++ b/nym-wallet/src/pages/bonding/mixnode/node-settings/ProfitMarginModal.tsx @@ -1,15 +1,16 @@ import * as React from 'react'; import { useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; -import { Divider, Stack, Typography } from '@mui/material'; +import { Box, Divider, Stack, Typography } from '@mui/material'; import { MajorCurrencyAmount } from '@nymproject/types'; import { SimpleDialog, TextFieldInput } from '../../components'; -import schema from './schema'; +import { Node as NodeIcon } from '../../../../svg-icons/node'; +import getSchema from './schema'; export interface Props { open: boolean; onClose: () => void; - onSubmit: (pm: number) => Promise; + onConfirm: (pm: number) => void; estimatedOpReward: MajorCurrencyAmount; currentPm: number; } @@ -18,15 +19,14 @@ interface FormData { profitMargin: number; } -const NodeSettingsModal = ({ open, onClose, onSubmit, estimatedOpReward, currentPm }: Props) => { +const NodeSettingsModal = ({ open, onClose, onConfirm, estimatedOpReward, currentPm }: Props) => { const { control, - setValue, - setError, handleSubmit, + reset, formState: { errors }, } = useForm({ - resolver: yupResolver(schema), + resolver: yupResolver(getSchema(currentPm)), defaultValues: { profitMargin: currentPm, }, @@ -35,37 +35,48 @@ const NodeSettingsModal = ({ open, onClose, onSubmit, estimatedOpReward, current return ( onSubmit(data.profitMargin))} - title="Node Settings" + onClose={() => { + reset(); + onClose(); + }} + onConfirm={handleSubmit(async (data) => onConfirm(data.profitMargin))} + title={ + + + Node Settings + + } subTitle="System Variables" confirmButton="Next" closeButton + disabled={Boolean(errors?.profitMargin)} > -
- - - - Estimated operator reward for 10% PM - {`~${estimatedOpReward.amount} ${estimatedOpReward.denom}`} - - - Est. fee for this transaction will be cauculated in the next page + +
+ + + + Estimated operator reward for 10% PM + {`~${estimatedOpReward.amount} ${estimatedOpReward.denom}`} + + + Est. fee for this transaction will be cauculated in the next page +
); }; diff --git a/nym-wallet/src/pages/bonding/mixnode/node-settings/SummaryModal.tsx b/nym-wallet/src/pages/bonding/mixnode/node-settings/SummaryModal.tsx new file mode 100644 index 0000000000..20d4626cf5 --- /dev/null +++ b/nym-wallet/src/pages/bonding/mixnode/node-settings/SummaryModal.tsx @@ -0,0 +1,47 @@ +import * as React from 'react'; +import { Divider, Stack, Typography } from '@mui/material'; +import { MajorCurrencyAmount } from '@nymproject/types'; +import { SimpleDialog } from '../../components'; + +export interface Props { + open: boolean; + onClose: () => void; + onConfirm: () => void; + onCancel: () => void; + currentPm: number; + newPm: number; + fee: MajorCurrencyAmount; +} + +const SummaryModal = ({ open, onClose, onConfirm, onCancel, currentPm, newPm, fee }: Props) => ( + + + Current profit margin + {`${currentPm}%`} + + + + New profit margin + {`${newPm}%`} + + + + Fee for this operation + {`${fee.amount} ${fee.denom}`} + + +); + +export default SummaryModal; diff --git a/nym-wallet/src/pages/bonding/mixnode/node-settings/schema.ts b/nym-wallet/src/pages/bonding/mixnode/node-settings/schema.ts index e53c668d1e..14ad89fb2a 100644 --- a/nym-wallet/src/pages/bonding/mixnode/node-settings/schema.ts +++ b/nym-wallet/src/pages/bonding/mixnode/node-settings/schema.ts @@ -1,7 +1,8 @@ import { number, object } from 'yup'; -const schema = object().shape({ - profitMargin: number().required('Profit Percentage is required').min(0).max(100), -}); +const getSchema = (currentPm: number) => + object().shape({ + profitMargin: number().required('Profit Percentage is required').min(0).max(100).notOneOf([currentPm]), + }); -export default schema; +export default getSchema;