Merge pull request #1492 from nymtech/feature/delegating_ui_update
feat(wallet-delegation): new confirmation modal ui
This commit is contained in:
@@ -10,9 +10,9 @@ export default {
|
||||
|
||||
const Template: ComponentStory<typeof ConfirmTx> = (args) => (
|
||||
<ConfirmTx {...args}>
|
||||
<ModalListItem label="Transaction type" value="Bond" divider />
|
||||
<ModalListItem label="Current bond" value="100 NYM" divider />
|
||||
<ModalListItem label="Additional bond" value="50 NYM" divider />
|
||||
<ModalListItem label="Transaction type:" value="Bond" divider />
|
||||
<ModalListItem label="Current bond:" value="100 NYM" divider />
|
||||
<ModalListItem label="Additional bond:" value="50 NYM" divider />
|
||||
</ConfirmTx>
|
||||
);
|
||||
|
||||
|
||||
@@ -168,8 +168,8 @@ export const DelegateModal: React.FC<{
|
||||
onPrev={resetFeeState}
|
||||
onConfirm={handleOk}
|
||||
>
|
||||
<ModalListItem label="Node identity key" value={identityKey} divider />
|
||||
<ModalListItem label="Amount" value={`${amount} ${denom.toUpperCase()}`} divider />
|
||||
<ModalListItem label="Node identity key:" value={identityKey} divider />
|
||||
<ModalListItem label="Amount:" value={`${amount} ${denom.toUpperCase()}`} divider />
|
||||
</ConfirmTx>
|
||||
);
|
||||
}
|
||||
@@ -184,23 +184,24 @@ export const DelegateModal: React.FC<{
|
||||
}
|
||||
}}
|
||||
header={header || 'Delegate'}
|
||||
subHeader="Delegate to mixnode"
|
||||
okLabel={buttonText || 'Delegate stake'}
|
||||
okDisabled={!isValidated}
|
||||
sx={sx}
|
||||
backdropProps={backdropProps}
|
||||
>
|
||||
<IdentityKeyFormField
|
||||
required
|
||||
fullWidth
|
||||
placeholder="Node identity key"
|
||||
onChanged={handleIdentityKeyChanged}
|
||||
initialValue={identityKey}
|
||||
readOnly={Boolean(initialIdentityKey)}
|
||||
textFieldProps={{
|
||||
autoFocus: !initialIdentityKey,
|
||||
}}
|
||||
/>
|
||||
<Box sx={{ mt: 2 }}>
|
||||
<IdentityKeyFormField
|
||||
required
|
||||
fullWidth
|
||||
placeholder="Node identity key"
|
||||
onChanged={handleIdentityKeyChanged}
|
||||
initialValue={identityKey}
|
||||
readOnly={Boolean(initialIdentityKey)}
|
||||
textFieldProps={{
|
||||
autoFocus: !initialIdentityKey,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Typography
|
||||
component="div"
|
||||
textAlign="left"
|
||||
@@ -230,29 +231,30 @@ export const DelegateModal: React.FC<{
|
||||
{errorAmount}
|
||||
</Typography>
|
||||
<Box sx={{ mt: 3 }}>
|
||||
<ModalListItem label="Account balance" value={accountBalance} divider />
|
||||
<ModalListItem label="Account balance:" value={accountBalance} divider strong />
|
||||
</Box>
|
||||
|
||||
<ModalListItem label="Rewards payout interval" value={rewardInterval} hidden divider />
|
||||
<ModalListItem label="Rewards payout interval:" value={rewardInterval} hidden divider />
|
||||
<ModalListItem
|
||||
label="Node profit margin"
|
||||
label="Node profit margin:"
|
||||
value={`${profitMarginPercentage ? `${profitMarginPercentage}%` : '-'}`}
|
||||
hidden={profitMarginPercentage === undefined}
|
||||
divider
|
||||
/>
|
||||
<ModalListItem
|
||||
label="Node uptime"
|
||||
label="Node avg. uptime:"
|
||||
value={`${nodeUptimePercentage ? `${nodeUptimePercentage}%` : '-'}`}
|
||||
hidden={nodeUptimePercentage === undefined}
|
||||
divider
|
||||
/>
|
||||
|
||||
<ModalListItem
|
||||
label="Node est. reward per epoch"
|
||||
label="Node est. reward per epoch:"
|
||||
value={`${estimatedReward} ${denom.toUpperCase()}`}
|
||||
hidden
|
||||
divider
|
||||
/>
|
||||
<ModalListItem label="Est. fee for this transaction will be calculated in the next page" />
|
||||
</SimpleModal>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -29,9 +29,6 @@ const transactionForDarkTheme = {
|
||||
url: 'https://sandbox-blocks.nymtech.net/transactions/11ED7B9E21534A9421834F52FED5103DC6E982949C06335F5E12EFC71DAF0CFO',
|
||||
hash: '11ED7B9E21534A9421834F52FED5103DC6E982949C06335F5E12EFC71DAF0CF0',
|
||||
};
|
||||
const balance = '104 NYMT';
|
||||
const balanceVested = '12 NYMT';
|
||||
const recipient = 'nymt1923pujepxfnv8dqyxqrl078s4ysf3xn2p7z2xa';
|
||||
|
||||
const Content: React.FC<{ children: React.ReactElement<any, any>; handleClick: () => void }> = ({
|
||||
children,
|
||||
@@ -78,8 +75,6 @@ export const DelegateSuccess = () => {
|
||||
status="success"
|
||||
action="delegate"
|
||||
message="You delegated 5 NYM"
|
||||
recipient={recipient}
|
||||
balance={balance}
|
||||
transactions={theme.palette.mode === 'light' ? [transaction] : [transactionForDarkTheme]}
|
||||
{...storybookStyles(theme)}
|
||||
/>
|
||||
@@ -99,8 +94,6 @@ export const UndelegateSuccess = () => {
|
||||
status="success"
|
||||
action="undelegate"
|
||||
message="You undelegated 5 NYM"
|
||||
recipient={recipient}
|
||||
balance={balance}
|
||||
transactions={theme.palette.mode === 'light' ? [transaction] : [transactionForDarkTheme]}
|
||||
{...storybookStyles(theme)}
|
||||
/>
|
||||
@@ -120,8 +113,6 @@ export const RedeemSuccess = () => {
|
||||
status="success"
|
||||
action="redeem"
|
||||
message="42 NYM"
|
||||
recipient={recipient}
|
||||
balance={balance}
|
||||
transactions={
|
||||
theme.palette.mode === 'light'
|
||||
? [transaction, transaction]
|
||||
@@ -145,9 +136,6 @@ export const RedeemWithVestedSuccess = () => {
|
||||
status="success"
|
||||
action="redeem"
|
||||
message="42 NYM"
|
||||
recipient={recipient}
|
||||
balance={balance}
|
||||
balanceVested={balanceVested}
|
||||
transactions={
|
||||
theme.palette.mode === 'light'
|
||||
? [transaction, transaction]
|
||||
@@ -171,8 +159,6 @@ export const RedeemAllSuccess = () => {
|
||||
status="success"
|
||||
action="redeem-all"
|
||||
message="42 NYM"
|
||||
recipient={recipient}
|
||||
balance={balance}
|
||||
transactions={
|
||||
theme.palette.mode === 'light'
|
||||
? [transaction, transaction]
|
||||
@@ -196,8 +182,6 @@ export const Error = () => {
|
||||
status="error"
|
||||
action="redeem-all"
|
||||
message="Minim esse veniam Lorem id velit Lorem eu eu est. Excepteur labore sunt do proident proident sint aliquip consequat Lorem sint non nulla ad excepteur."
|
||||
recipient={recipient}
|
||||
balance={balance}
|
||||
transactions={theme.palette.mode === 'light' ? [transaction] : [transactionForDarkTheme]}
|
||||
{...storybookStyles(theme)}
|
||||
/>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from 'react';
|
||||
import { Box, Button, Modal, Typography, SxProps } from '@mui/material';
|
||||
import { Box, Button, Modal, Typography, SxProps, Stack } from '@mui/material';
|
||||
import { Link } from '@nymproject/react/link/Link';
|
||||
import { Console } from 'src/utils/console';
|
||||
import { modalStyle } from '../Modals/styles';
|
||||
import { LoadingModal } from '../Modals/LoadingModal';
|
||||
import { ConfirmationModal } from '../Modals/ConfirmationModal';
|
||||
|
||||
export type ActionType = 'delegate' | 'undelegate' | 'redeem' | 'redeem-all' | 'compound';
|
||||
|
||||
@@ -15,9 +16,9 @@ const actionToHeader = (action: ActionType): string => {
|
||||
case 'redeem-all':
|
||||
return 'All rewards redeemed successfully';
|
||||
case 'delegate':
|
||||
return 'Delegation complete';
|
||||
return 'Delegation successful';
|
||||
case 'undelegate':
|
||||
return 'Undelegation complete';
|
||||
return 'Undelegation successful';
|
||||
case 'compound':
|
||||
return 'Rewards compounded successfully';
|
||||
default:
|
||||
@@ -29,9 +30,6 @@ export type DelegationModalProps = {
|
||||
status: 'loading' | 'success' | 'error';
|
||||
action: ActionType;
|
||||
message?: string;
|
||||
recipient?: string;
|
||||
balance?: string;
|
||||
balanceVested?: string;
|
||||
transactions?: {
|
||||
url: string;
|
||||
hash: string;
|
||||
@@ -45,20 +43,7 @@ export const DelegationModal: React.FC<
|
||||
sx?: SxProps;
|
||||
backdropProps?: object;
|
||||
}
|
||||
> = ({
|
||||
status,
|
||||
action,
|
||||
message,
|
||||
recipient,
|
||||
balance,
|
||||
balanceVested,
|
||||
transactions,
|
||||
open,
|
||||
onClose,
|
||||
children,
|
||||
sx,
|
||||
backdropProps,
|
||||
}) => {
|
||||
> = ({ status, action, message, transactions, open, onClose, children, sx, backdropProps }) => {
|
||||
if (status === 'loading') return <LoadingModal sx={sx} backdropProps={backdropProps} />;
|
||||
|
||||
if (status === 'error') {
|
||||
@@ -81,54 +66,28 @@ export const DelegationModal: React.FC<
|
||||
}
|
||||
|
||||
transactions?.map((transaction) => Console.log('action', action, 'status', status, 'key', transaction.hash));
|
||||
return (
|
||||
<Modal open={open} onClose={onClose} BackdropProps={backdropProps}>
|
||||
<Box sx={{ ...modalStyle, ...sx }} textAlign="center">
|
||||
<Typography color={(theme) => theme.palette.success.main} mb={1}>
|
||||
{actionToHeader(action)}
|
||||
</Typography>
|
||||
<Typography mb={3} color="text.primary">
|
||||
{message}
|
||||
</Typography>
|
||||
|
||||
{recipient && (
|
||||
<Typography mb={1} fontSize="small" color={(theme) => theme.palette.text.secondary}>
|
||||
Recipient: {recipient}
|
||||
</Typography>
|
||||
return (
|
||||
<ConfirmationModal
|
||||
open={open}
|
||||
onConfirm={onClose || (() => {})}
|
||||
title={actionToHeader(action)}
|
||||
confirmButton="Done"
|
||||
>
|
||||
<Stack alignItems="center" spacing={2} mb={0}>
|
||||
{message && <Typography>{message}</Typography>}
|
||||
{transactions?.length === 1 && (
|
||||
<Link href={transactions[0].url} target="_blank" sx={{ ml: 1 }} text="View on blockchain" noIcon />
|
||||
)}
|
||||
{balanceVested ? (
|
||||
<>
|
||||
<Typography mb={1} fontSize="small" color={(theme) => theme.palette.text.secondary}>
|
||||
Your current balance: {balance?.toUpperCase()}
|
||||
</Typography>
|
||||
<Typography mb={1} fontSize="small" color={(theme) => theme.palette.text.secondary}>
|
||||
({balanceVested.toUpperCase()} is unlocked in your vesting account)
|
||||
</Typography>
|
||||
</>
|
||||
) : (
|
||||
<Typography mb={1} fontSize="small" color={(theme) => theme.palette.text.secondary}>
|
||||
Your current balance: {balance?.toUpperCase()}
|
||||
</Typography>
|
||||
)}
|
||||
{transactions && (
|
||||
<Typography mb={1} fontSize="small" color={(theme) => theme.palette.text.secondary}>
|
||||
Check the transaction {transactions.length > 1 ? 'hashes' : 'hash'}:
|
||||
{transactions.map((transaction) => (
|
||||
<Link
|
||||
key={transaction.hash}
|
||||
href={transaction.url}
|
||||
target="_blank"
|
||||
sx={{ ml: 1 }}
|
||||
text={transaction.hash.slice(0, 6)}
|
||||
/>
|
||||
{transactions && transactions.length > 1 && (
|
||||
<Stack alignItems="center" spacing={1}>
|
||||
<Typography>View the transactions on blockchain:</Typography>
|
||||
{transactions.map(({ url, hash }) => (
|
||||
<Link href={url} target="_blank" sx={{ ml: 1 }} text={hash.slice(0, 6)} key={hash} noIcon />
|
||||
))}
|
||||
</Typography>
|
||||
</Stack>
|
||||
)}
|
||||
{children}
|
||||
<Button variant="contained" sx={{ mt: 3 }} size="large" onClick={onClose}>
|
||||
Finish
|
||||
</Button>
|
||||
</Box>
|
||||
</Modal>
|
||||
</Stack>
|
||||
</ConfirmationModal>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -55,7 +55,7 @@ export const UndelegateModal: React.FC<{
|
||||
/>
|
||||
|
||||
<Box sx={{ mt: 3 }}>
|
||||
<ModalListItem label="Delegation amount" value={`${amount} ${currency}`} divider />
|
||||
<ModalListItem label="Delegation amount:" value={`${amount} ${currency}`} divider />
|
||||
</Box>
|
||||
|
||||
<Typography mb={5} fontSize="smaller" sx={{ color: 'text.primary' }}>
|
||||
|
||||
@@ -13,5 +13,5 @@ const getValue = ({ fee, isLoading, error }: TFeeProps) => {
|
||||
};
|
||||
|
||||
export const ModalFee = ({ fee, isLoading, error }: TFeeProps) => (
|
||||
<ModalListItem label="Estimated fee for this operation" value={getValue({ fee, isLoading, error })} />
|
||||
<ModalListItem label="Estimated fee for this operation:" value={getValue({ fee, isLoading, error })} />
|
||||
);
|
||||
|
||||
@@ -7,20 +7,22 @@ export const ModalListItem: React.FC<{
|
||||
divider?: boolean;
|
||||
hidden?: boolean;
|
||||
strong?: boolean;
|
||||
value: React.ReactNode;
|
||||
value?: React.ReactNode;
|
||||
}> = ({ label, value, hidden, divider, strong }) => (
|
||||
<Box sx={{ display: hidden ? 'none' : 'block' }}>
|
||||
<Stack direction="row" justifyContent="space-between">
|
||||
<Typography fontSize="smaller" fontWeight={strong ? 600 : undefined} sx={{ color: 'text.primary' }}>
|
||||
{label}:
|
||||
</Typography>
|
||||
<Typography
|
||||
fontSize="smaller"
|
||||
fontWeight={strong ? 600 : undefined}
|
||||
sx={{ color: 'text.primary', textTransform: 'uppercase' }}
|
||||
>
|
||||
{value}
|
||||
{label}
|
||||
</Typography>
|
||||
{value && (
|
||||
<Typography
|
||||
fontSize="smaller"
|
||||
fontWeight={strong ? 600 : undefined}
|
||||
sx={{ color: 'text.primary', textTransform: 'uppercase' }}
|
||||
>
|
||||
{value}
|
||||
</Typography>
|
||||
)}
|
||||
</Stack>
|
||||
{divider && <ModalDivider />}
|
||||
</Box>
|
||||
|
||||
@@ -39,11 +39,11 @@ export const SendDetailsModal = ({
|
||||
backdropProps={backdropProps}
|
||||
>
|
||||
<Stack gap={0.5} sx={{ mt: 4 }}>
|
||||
<ModalListItem label="From" value={fromAddress} divider />
|
||||
<ModalListItem label="To" value={toAddress} divider />
|
||||
<ModalListItem label="Amount" value={`${amount?.amount} ${denom.toUpperCase()}`} divider />
|
||||
<ModalListItem label="From:" value={fromAddress} divider />
|
||||
<ModalListItem label="To:" value={toAddress} divider />
|
||||
<ModalListItem label="Amount:" value={`${amount?.amount} ${denom.toUpperCase()}`} divider />
|
||||
<ModalListItem
|
||||
label="Fee for this transaction"
|
||||
label="Fee for this transaction:"
|
||||
value={!fee ? 'n/a' : `${fee.amount?.amount} ${fee.amount?.denom}`}
|
||||
divider
|
||||
/>
|
||||
|
||||
@@ -77,8 +77,8 @@ export const SendInputModal = ({
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Stack gap={0.5} sx={{ mt: 2 }}>
|
||||
<ModalListItem label="Account balance" value={balance} divider strong />
|
||||
<ModalListItem label="Your address" value={fromAddress} divider />
|
||||
<ModalListItem label="Account balance:" value={balance} divider strong />
|
||||
<ModalListItem label="Your address:" value={fromAddress} divider />
|
||||
<Typography fontSize="smaller" sx={{ color: 'text.primary' }}>
|
||||
Est. fee for this transaction will be show on the next page
|
||||
</Typography>
|
||||
|
||||
@@ -87,12 +87,12 @@ export const TransferModal = ({ onClose }: { onClose: () => void }) => {
|
||||
) : (
|
||||
<>
|
||||
<ModalListItem
|
||||
label="Unlocked transferrable tokens"
|
||||
label="Unlocked transferrable tokens:"
|
||||
value={`${userBalance.tokenAllocation?.spendable} ${clientDetails?.display_mix_denom.toUpperCase()}`}
|
||||
divider
|
||||
/>
|
||||
<ModalListItem
|
||||
label="Est. fee for this transaction"
|
||||
label="Est. fee for this transaction:"
|
||||
value={fee ? `${fee.amount?.amount} ${fee.amount?.denom}` : <CircularProgress size={15} />}
|
||||
divider
|
||||
/>
|
||||
|
||||
@@ -20,8 +20,8 @@ export const ConfirmationModal = ({
|
||||
}) => (
|
||||
<SimpleModal header="Bond confirmation" open onOk={onConfirm} okLabel="Confirm" hideCloseIcon onBack={onPrev}>
|
||||
<Box sx={{ mt: 3 }}>
|
||||
<ModalListItem label="Mixnode identity" value={identity} />
|
||||
<ModalListItem label="Amount" value={`${amount.amount} ${amount.denom}`} />
|
||||
<ModalListItem label="Mixnode identity:" value={identity} />
|
||||
<ModalListItem label="Amount:" value={`${amount.amount} ${amount.denom}`} />
|
||||
<ModalFee fee={fee} isLoading={false} />
|
||||
</Box>
|
||||
</SimpleModal>
|
||||
|
||||
@@ -138,7 +138,7 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => {
|
||||
setConfirmationModalProps({
|
||||
status: 'success',
|
||||
action: 'delegate',
|
||||
message: 'Delegations can take up to one hour to process',
|
||||
message: 'This operation can take up to one hour to process',
|
||||
...balances,
|
||||
transactions: [
|
||||
{ url: `${urls(network).blockExplorer}/transaction/${tx.transaction_hash}`, hash: tx.transaction_hash },
|
||||
@@ -240,11 +240,9 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => {
|
||||
|
||||
try {
|
||||
const txs = await claimRewards(identityKey, fee);
|
||||
const bal = await userBalance();
|
||||
setConfirmationModalProps({
|
||||
status: 'success',
|
||||
action: 'redeem',
|
||||
balance: bal?.printable_balance || '-',
|
||||
transactions: txs.map((tx) => ({
|
||||
url: `${urls(network).blockExplorer}/transaction/${tx.transaction_hash}`,
|
||||
hash: tx.transaction_hash,
|
||||
@@ -270,11 +268,9 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => {
|
||||
|
||||
try {
|
||||
const txs = await compoundRewards(identityKey, fee);
|
||||
const bal = await userBalance();
|
||||
setConfirmationModalProps({
|
||||
status: 'success',
|
||||
action: 'compound',
|
||||
balance: bal?.printable_balance || '-',
|
||||
transactions: txs.map((tx) => ({
|
||||
url: `${urls(network).blockExplorer}/transaction/${tx.transaction_hash}`,
|
||||
hash: tx.transaction_hash,
|
||||
|
||||
Reference in New Issue
Block a user