From 96f2718b940db80cda4ab601ceba336a2b59bb0b Mon Sep 17 00:00:00 2001 From: Fouad Date: Fri, 29 Apr 2022 12:53:52 +0100 Subject: [PATCH] Feature/show pending delegations (#1229) * remove unused import * use correct types * set up pending delegations * remove unused import --- nym-wallet/Cargo.lock | 3 + .../src/pages/settings/useSettingsState.ts | 8 +- .../src/pages/undelegate/PendingEvents.tsx | 46 +++++ nym-wallet/src/pages/undelegate/index.tsx | 164 +++++++++++------- .../rust/inclusionprobabilityresponse.ts | 7 +- 5 files changed, 152 insertions(+), 76 deletions(-) create mode 100644 nym-wallet/src/pages/undelegate/PendingEvents.tsx diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index c63ccd0332..b1d825e27a 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -2401,6 +2401,7 @@ checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg 1.1.0", "hashbrown", + "serde", ] [[package]] @@ -4088,6 +4089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6b5a3c80cea1ab61f4260238409510e814e38b4b563c06044edf91e7dc070e3" dependencies = [ "dyn-clone", + "indexmap", "schemars_derive", "serde", "serde_json", @@ -5388,6 +5390,7 @@ name = "validator-api-requests" version = "0.1.0" dependencies = [ "mixnet-contract-common", + "schemars", "serde", ] diff --git a/nym-wallet/src/pages/settings/useSettingsState.ts b/nym-wallet/src/pages/settings/useSettingsState.ts index dc42750a4c..239f3d4b08 100644 --- a/nym-wallet/src/pages/settings/useSettingsState.ts +++ b/nym-wallet/src/pages/settings/useSettingsState.ts @@ -1,12 +1,6 @@ import { useContext, useEffect, useState } from 'react'; import { ClientContext } from '../../context/main'; -import { -// getMixnodeRewardEstimation, - getMixnodeStakeSaturation, - getMixnodeStatus, - minorToMajor, - getInclusionProbability, -} from '../../requests'; +import { getMixnodeStakeSaturation, getMixnodeStatus, getInclusionProbability } from '../../requests'; import { MixnodeStatus, InclusionProbabilityResponse } from '../../types'; export const useSettingsState = (shouldUpdate: boolean) => { diff --git a/nym-wallet/src/pages/undelegate/PendingEvents.tsx b/nym-wallet/src/pages/undelegate/PendingEvents.tsx new file mode 100644 index 0000000000..b3c66b12ae --- /dev/null +++ b/nym-wallet/src/pages/undelegate/PendingEvents.tsx @@ -0,0 +1,46 @@ +import React, { useCallback, useContext, useEffect, useState } from 'react'; +import { Table, TableCell, TableHead, TableRow } from '@mui/material'; +import { minorToMajor } from 'src/requests'; +import { DelegationResult } from 'src/types'; +import { ClientContext } from 'src/context/main'; + +export const PendingEvents = ({ + pendingDelegations, + show, +}: { + pendingDelegations: DelegationResult[]; + show: boolean; +}) => { + const [mapped, setMapped] = useState>([]); + const { currency } = useContext(ClientContext); + + const mapToMajorValue = useCallback(async () => { + const mappedToMajor = await Promise.all( + pendingDelegations.map(async (pendingDelegation) => { + const majorValue = await minorToMajor(pendingDelegation.amount?.amount || ''); + return { ...pendingDelegation, majorValue: majorValue.amount }; + }), + ); + setMapped(mappedToMajor); + }, [pendingDelegations]); + + useEffect(() => { + mapToMajorValue(); + }, []); + return show ? ( + + + + Address + Amount + + + {mapped.map((delegation) => ( + + {delegation.target_address} + {`${delegation.majorValue} ${currency?.major}`} + + ))} +
+ ) : null; +}; diff --git a/nym-wallet/src/pages/undelegate/index.tsx b/nym-wallet/src/pages/undelegate/index.tsx index 13127d4172..6136b64a29 100644 --- a/nym-wallet/src/pages/undelegate/index.tsx +++ b/nym-wallet/src/pages/undelegate/index.tsx @@ -1,5 +1,6 @@ import React, { useContext, useEffect, useState } from 'react'; -import { Alert, AlertTitle, Box, Button, CircularProgress } from '@mui/material'; +import { Alert, AlertTitle, Box, Button, CircularProgress, Grid, IconButton } from '@mui/material'; +import { ArrowDropDown, ArrowDropUp } from '@mui/icons-material'; import { EnumRequestStatus, NymCard, RequestStatus } from '../../components'; import { UndelegateForm } from './UndelegateForm'; import { @@ -8,10 +9,11 @@ import { getPendingVestingDelegations, getReverseMixDelegations, } from '../../requests'; -import { Epoch, PendingUndelegate, TPagedDelegations } from '../../types'; +import { DelegationResult, Epoch, PendingUndelegate, TPagedDelegations } from '../../types'; import { ClientContext } from '../../context/main'; import { PageLayout } from '../../layouts'; import { removeObjectDuplicates } from '../../utils'; +import { PendingEvents } from './PendingEvents'; export const Undelegate = () => { const [message, setMessage] = useState(); @@ -19,7 +21,9 @@ export const Undelegate = () => { const [isLoading, setIsLoading] = useState(true); const [pagedDelegations, setPagesDelegations] = useState(); const [pendingUndelegations, setPendingUndelegations] = useState(); + const [pendingDelegations, setPendingDelegations] = useState(); const [currentEndEpoch, setCurrentEndEpoch] = useState(); + const [showPendingDelegations, setShowPendingDelegations] = useState(false); const { clientDetails } = useContext(ClientContext); @@ -30,10 +34,14 @@ export const Undelegate = () => { const pendingUndelegationEvents = [...pendingEvents, ...pendingVestingEvents] .filter((evt): evt is { Undelegate: PendingUndelegate } => 'Undelegate' in evt) .map((e) => ({ ...e.Undelegate })); + const pendingDelegationEvents = [...pendingEvents, ...pendingVestingEvents] + .filter((evt): evt is { Delegate: DelegationResult } => 'Delegate' in evt) + .map((e) => ({ ...e.Delegate })); const epoch = await getCurrentEpoch(); setCurrentEndEpoch(epoch.end); setPendingUndelegations(pendingUndelegationEvents); + setPendingDelegations(pendingDelegationEvents); setPagesDelegations({ ...mixnodeDelegations, delegations: removeObjectDuplicates(mixnodeDelegations.delegations, 'node_identity'), @@ -60,78 +68,102 @@ export const Undelegate = () => { return ( - - {isLoading && ( - - - - )} - <> - {status === EnumRequestStatus.initial && pagedDelegations && ( - { - setMessage(m); - setStatus(EnumRequestStatus.error); - refresh(); - }} - onSuccess={(m) => { - setMessage(m); - setStatus(EnumRequestStatus.success); - refresh(); - }} - /> - )} - {status !== EnumRequestStatus.initial && ( - <> - - An error occurred with the request: {message} - - } - Success={ - - Undelegation request complete - {message} - - } - /> + + + + {isLoading && ( - + + )} + <> + {status === EnumRequestStatus.initial && pagedDelegations && ( + { + setMessage(m); + setStatus(EnumRequestStatus.error); + refresh(); + }} + onSuccess={(m) => { + setMessage(m); + setStatus(EnumRequestStatus.success); + refresh(); + }} + /> + )} + {status !== EnumRequestStatus.initial && ( + <> + + An error occurred with the request: {message} + + } + Success={ + + Undelegation request complete + {message} + + } + /> + + + + + )} - )} - - + + + {pendingDelegations?.length && ( + + setShowPendingDelegations((show) => !show)}> + {!showPendingDelegations ? : } + + } + > + {pendingDelegations ? ( + + ) : ( +
No pending delegations
+ )} +
+
+ )} +
); }; diff --git a/nym-wallet/src/types/rust/inclusionprobabilityresponse.ts b/nym-wallet/src/types/rust/inclusionprobabilityresponse.ts index 0c1c8e2b59..ec83a70b04 100644 --- a/nym-wallet/src/types/rust/inclusionprobabilityresponse.ts +++ b/nym-wallet/src/types/rust/inclusionprobabilityresponse.ts @@ -1,3 +1,4 @@ -import type { SelectionChance } from "./selectionchance"; - -export interface InclusionProbabilityResponse { in_active: SelectionChance, in_reserve: SelectionChance, } \ No newline at end of file +export interface InclusionProbabilityResponse { + in_active: number; + in_reserve: number; +}