Merge pull request #3982 from nymtech/bug/issue-3981/wallet-delegations-orderby-cp
Wallet: Fix delegation sorting for Cost Params
This commit is contained in:
@@ -32,7 +32,7 @@ jobs:
|
||||
- name: Install mdbook plugins
|
||||
run: |
|
||||
cargo install --vers "=0.2.2" mdbook-variables && cargo install \
|
||||
--vers "^1.8.0" mdbook-admonish install && cargo install --vers \
|
||||
--vers "^1.8.0" mdbook-admonish install --force && cargo install --vers \
|
||||
"^0.1.2" mdbook-last-changed && cargo install --vers "^0.1.2" mdbook-theme \
|
||||
&& cargo install --vers "^0.7.7" mdbook-linkcheck
|
||||
- name: Build all projects in documentation/ & move to ~/dist/docs/
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@nymproject/mui-theme": "^1.0.0",
|
||||
"@nymproject/react": "^1.0.0",
|
||||
"@nymproject/types": "^1.0.0",
|
||||
"@nymproject/node-tester": ">=1.2.0-rc.10 || ^1",
|
||||
"@nymproject/node-tester": "^1.0.0",
|
||||
"@storybook/react": "^6.5.15",
|
||||
"@tauri-apps/api": "^1.2.0",
|
||||
"@tauri-apps/tauri-forage": "^1.0.0-beta.2",
|
||||
|
||||
@@ -29,7 +29,7 @@ export const items: DelegationWithEverything[] = [
|
||||
accumulated_by_operator: { amount: '100', denom: 'nym' },
|
||||
owner: '',
|
||||
block_height: BigInt(100),
|
||||
stake_saturation: '0.5',
|
||||
stake_saturation: '0.25',
|
||||
avg_uptime_percent: 0.5,
|
||||
uses_vesting_contract_tokens: false,
|
||||
pending_events: [],
|
||||
@@ -38,7 +38,7 @@ export const items: DelegationWithEverything[] = [
|
||||
{
|
||||
mix_id: 2,
|
||||
node_identity: 'DT8S942S8AQs2zKHS9SVo1GyHmuca3pfL2uLhLksJ3D8',
|
||||
amount: { amount: '100', denom: 'nym' },
|
||||
amount: { amount: '1010', denom: 'nym' },
|
||||
delegated_on_iso_datetime: new Date(2021, 1, 2).toDateString(),
|
||||
unclaimed_rewards: { amount: '0.05', denom: 'nym' },
|
||||
cost_params: {
|
||||
@@ -49,11 +49,11 @@ export const items: DelegationWithEverything[] = [
|
||||
},
|
||||
},
|
||||
accumulated_by_delegates: { amount: '50', denom: 'nym' },
|
||||
accumulated_by_operator: { amount: '100', denom: 'nym' },
|
||||
accumulated_by_operator: { amount: '200', denom: 'nym' },
|
||||
owner: '',
|
||||
block_height: BigInt(4000),
|
||||
stake_saturation: '0.5',
|
||||
avg_uptime_percent: 0.1,
|
||||
stake_saturation: '0.43',
|
||||
avg_uptime_percent: 0.22,
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
@@ -61,18 +61,18 @@ export const items: DelegationWithEverything[] = [
|
||||
{
|
||||
mix_id: 3,
|
||||
node_identity: '',
|
||||
amount: { amount: '100', denom: 'nym' },
|
||||
amount: { amount: '300', denom: 'nym' },
|
||||
delegated_on_iso_datetime: new Date(2021, 1, 2).toDateString(),
|
||||
unclaimed_rewards: { amount: '0.05', denom: 'nym' },
|
||||
cost_params: {
|
||||
profit_margin_percent: '0.1122323949234',
|
||||
interval_operating_cost: {
|
||||
amount: '40',
|
||||
amount: '50',
|
||||
denom: 'nym',
|
||||
},
|
||||
},
|
||||
accumulated_by_delegates: { amount: '50', denom: 'nym' },
|
||||
accumulated_by_operator: { amount: '100', denom: 'nym' },
|
||||
accumulated_by_operator: { amount: '300', denom: 'nym' },
|
||||
owner: '',
|
||||
block_height: BigInt(4000),
|
||||
stake_saturation: '0.5',
|
||||
@@ -84,18 +84,18 @@ export const items: DelegationWithEverything[] = [
|
||||
{
|
||||
mix_id: 4,
|
||||
node_identity: 'DT8S942S8AQs2zKHS9SVo1GyHmuca3pfL2uLhLksJ3D8',
|
||||
amount: { amount: '100', denom: 'nym' },
|
||||
amount: { amount: '201', denom: 'nym' },
|
||||
delegated_on_iso_datetime: new Date(2021, 1, 2).toDateString(),
|
||||
unclaimed_rewards: { amount: '0.05', denom: 'nym' },
|
||||
cost_params: {
|
||||
profit_margin_percent: '0.1122323949234',
|
||||
interval_operating_cost: {
|
||||
amount: '40',
|
||||
amount: '60',
|
||||
denom: 'nym',
|
||||
},
|
||||
},
|
||||
accumulated_by_delegates: { amount: '50', denom: 'nym' },
|
||||
accumulated_by_operator: { amount: '100', denom: 'nym' },
|
||||
accumulated_by_operator: { amount: '202', denom: 'nym' },
|
||||
owner: '',
|
||||
block_height: BigInt(4000),
|
||||
stake_saturation: '0.5',
|
||||
@@ -113,7 +113,7 @@ export const items: DelegationWithEverything[] = [
|
||||
cost_params: {
|
||||
profit_margin_percent: '0.1122323949234',
|
||||
interval_operating_cost: {
|
||||
amount: '40',
|
||||
amount: '80',
|
||||
denom: 'nym',
|
||||
},
|
||||
},
|
||||
@@ -130,11 +130,11 @@ export const items: DelegationWithEverything[] = [
|
||||
{
|
||||
mix_id: 6,
|
||||
node_identity: '',
|
||||
amount: { amount: '100', denom: 'nym' },
|
||||
amount: { amount: '202', denom: 'nym' },
|
||||
delegated_on_iso_datetime: new Date(2021, 1, 2).toDateString(),
|
||||
unclaimed_rewards: { amount: '0.05', denom: 'nym' },
|
||||
cost_params: {
|
||||
profit_margin_percent: '0.1122323949234',
|
||||
profit_margin_percent: '0.8',
|
||||
interval_operating_cost: {
|
||||
amount: '40',
|
||||
denom: 'nym',
|
||||
@@ -155,9 +155,9 @@ export const items: DelegationWithEverything[] = [
|
||||
node_identity: 'FiojKW7oY9WQmLCiYAsCA21tpowZHS6zcUoyYm319p6Z',
|
||||
delegated_on_iso_datetime: new Date(2021, 1, 1).toDateString(),
|
||||
unclaimed_rewards: { amount: '0.05', denom: 'nym' },
|
||||
amount: { amount: '10', denom: 'nym' },
|
||||
amount: { amount: '202', denom: 'nym' },
|
||||
cost_params: {
|
||||
profit_margin_percent: '0.1122323949234',
|
||||
profit_margin_percent: '0.59',
|
||||
interval_operating_cost: {
|
||||
amount: '40',
|
||||
denom: 'nym',
|
||||
@@ -190,7 +190,7 @@ export const items: DelegationWithEverything[] = [
|
||||
accumulated_by_operator: { amount: '100', denom: 'nym' },
|
||||
owner: '',
|
||||
block_height: BigInt(4000),
|
||||
stake_saturation: '0.5',
|
||||
stake_saturation: '0.9',
|
||||
avg_uptime_percent: 0.1,
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
@@ -199,11 +199,11 @@ export const items: DelegationWithEverything[] = [
|
||||
{
|
||||
mix_id: 9,
|
||||
node_identity: '',
|
||||
amount: { amount: '100', denom: 'nym' },
|
||||
amount: { amount: '1000', denom: 'nym' },
|
||||
delegated_on_iso_datetime: new Date(2021, 1, 2).toDateString(),
|
||||
unclaimed_rewards: { amount: '0.05', denom: 'nym' },
|
||||
cost_params: {
|
||||
profit_margin_percent: '0.1122323949234',
|
||||
profit_margin_percent: '0.4',
|
||||
interval_operating_cost: {
|
||||
amount: '40',
|
||||
denom: 'nym',
|
||||
@@ -213,7 +213,7 @@ export const items: DelegationWithEverything[] = [
|
||||
accumulated_by_operator: { amount: '100', denom: 'nym' },
|
||||
owner: '',
|
||||
block_height: BigInt(4000),
|
||||
stake_saturation: '0.5',
|
||||
stake_saturation: '0.9',
|
||||
avg_uptime_percent: 0.1,
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
@@ -259,8 +259,8 @@ export const items: DelegationWithEverything[] = [
|
||||
accumulated_by_operator: { amount: '100', denom: 'nym' },
|
||||
owner: '',
|
||||
block_height: BigInt(4000),
|
||||
stake_saturation: '0.5',
|
||||
avg_uptime_percent: 0.1,
|
||||
stake_saturation: '0.56',
|
||||
avg_uptime_percent: 0.9,
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
|
||||
@@ -2,17 +2,17 @@ import React from 'react';
|
||||
import { Box, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TableSortLabel } from '@mui/material';
|
||||
import { visuallyHidden } from '@mui/utils';
|
||||
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
|
||||
import { orderBy as _orderBy } from 'lodash';
|
||||
import { DelegationWithEverything } from '@nymproject/types';
|
||||
import { useSortDelegations } from 'src/hooks/useSortDelegations';
|
||||
import { DelegationListItemActions } from './DelegationActions';
|
||||
import { isDelegation, isPendingDelegation, TDelegations } from '../../context/delegations';
|
||||
import { DelegationItem } from './DelegationItem';
|
||||
import { PendingDelegationItem } from './PendingDelegationItem';
|
||||
import { LoadingModal } from '../Modals/LoadingModal';
|
||||
import { isDelegation, isPendingDelegation, TDelegations } from '../../context/delegations';
|
||||
|
||||
type Order = 'asc' | 'desc';
|
||||
export type Order = 'asc' | 'desc';
|
||||
type AdditionalTypes = { profit_margin_percent: number; operating_cost: number };
|
||||
type SortingKeys = keyof AdditionalTypes | keyof DelegationWithEverything;
|
||||
export type SortingKeys = keyof AdditionalTypes | keyof DelegationWithEverything;
|
||||
|
||||
interface EnhancedTableProps {
|
||||
onRequestSort: (event: React.MouseEvent<unknown>, property: string) => void;
|
||||
@@ -83,10 +83,6 @@ const EnhancedTableHead: FCWithChildren<EnhancedTableProps> = ({ order, orderBy,
|
||||
};
|
||||
|
||||
// Pin delegations on unbonded nodes to the top of the list
|
||||
const sortByUnbondedMixnodeFirst = (a: any) => {
|
||||
if (!a.node_identity) return -1;
|
||||
return 1;
|
||||
};
|
||||
|
||||
export const DelegationList: FCWithChildren<{
|
||||
isLoading?: boolean;
|
||||
@@ -98,37 +94,13 @@ export const DelegationList: FCWithChildren<{
|
||||
const [order, setOrder] = React.useState<Order>('asc');
|
||||
const [orderBy, setOrderBy] = React.useState<SortingKeys>('delegated_on_iso_datetime');
|
||||
|
||||
const handleRequestSort = (event: React.MouseEvent<unknown>, property: any) => {
|
||||
const handleRequestSort = (_: React.MouseEvent<unknown>, property: any) => {
|
||||
const isAsc = orderBy === property && order === 'asc';
|
||||
setOrder(isAsc ? 'desc' : 'asc');
|
||||
setOrderBy(property);
|
||||
};
|
||||
|
||||
// if sorting by either amount or unclaimed_rewards
|
||||
// base sorting on their number counterparts
|
||||
const mapOrderBy = (key: SortingKeys) => {
|
||||
if (key === 'amount') return 'delegationValue';
|
||||
if (key === 'unclaimed_rewards') return 'operatorReward';
|
||||
if (key === 'profit_margin_percent') return 'profitMarginValue';
|
||||
if (key === 'operating_cost') return 'operatorCostValue';
|
||||
return key;
|
||||
};
|
||||
|
||||
const mapAndSort = (_items: TDelegations) => {
|
||||
const map = _items.map((item) =>
|
||||
isDelegation(item)
|
||||
? {
|
||||
...item,
|
||||
delegationValue: Number(item.amount.amount),
|
||||
operatorReward: Number(item.unclaimed_rewards?.amount),
|
||||
profitMarginValue: Number(item.cost_params?.profit_margin_percent),
|
||||
operatorCostValue: Number(item.cost_params?.interval_operating_cost),
|
||||
}
|
||||
: item,
|
||||
);
|
||||
|
||||
return _orderBy(map, mapOrderBy(orderBy), order).sort(sortByUnbondedMixnodeFirst);
|
||||
};
|
||||
const sorted = useSortDelegations(items, order, orderBy);
|
||||
|
||||
return (
|
||||
<TableContainer>
|
||||
@@ -136,8 +108,8 @@ export const DelegationList: FCWithChildren<{
|
||||
<Table sx={{ width: '100%' }}>
|
||||
<EnhancedTableHead order={order} orderBy={orderBy} onRequestSort={handleRequestSort} />
|
||||
<TableBody>
|
||||
{items?.length
|
||||
? mapAndSort(items).map((item: any) => {
|
||||
{sorted?.length
|
||||
? sorted.map((item: any) => {
|
||||
if (isPendingDelegation(item)) return <PendingDelegationItem item={item} explorerUrl={explorerUrl} />;
|
||||
if (isDelegation(item))
|
||||
return (
|
||||
|
||||
@@ -26,11 +26,11 @@ let mockDelegations: DelegationWithEverything[] = [
|
||||
cost_params: {
|
||||
profit_margin_percent: '0.04',
|
||||
interval_operating_cost: {
|
||||
amount: '40',
|
||||
amount: '20',
|
||||
denom: 'nym',
|
||||
},
|
||||
},
|
||||
stake_saturation: '0.5',
|
||||
stake_saturation: '0.2',
|
||||
avg_uptime_percent: 0.5,
|
||||
accumulated_by_delegates: { amount: '0', denom: 'nym' },
|
||||
accumulated_by_operator: { amount: '0', denom: 'nym' },
|
||||
@@ -51,7 +51,7 @@ let mockDelegations: DelegationWithEverything[] = [
|
||||
cost_params: {
|
||||
profit_margin_percent: '0.04',
|
||||
interval_operating_cost: {
|
||||
amount: '40',
|
||||
amount: '60',
|
||||
denom: 'nym',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { orderBy as _orderBy } from 'lodash';
|
||||
import { Order, SortingKeys } from 'src/components/Delegation/DelegationList';
|
||||
import { TDelegations, isDelegation } from 'src/context/delegations';
|
||||
|
||||
type MappedTypes = 'delegationValue' | 'operatorReward' | 'profitMarginValue' | 'operatorCostValue';
|
||||
|
||||
export const useSortDelegations = (delegationItems: TDelegations, order: Order, orderBy: SortingKeys) => {
|
||||
const unbondedDelegations = delegationItems.filter((delegation) => !delegation.node_identity);
|
||||
const delegations = delegationItems.filter((delegation) => delegation.node_identity);
|
||||
|
||||
// example of a mapped type in typescript
|
||||
|
||||
const mapOrderBy = (key: SortingKeys): MappedTypes | SortingKeys => {
|
||||
switch (key) {
|
||||
case 'amount':
|
||||
return 'delegationValue';
|
||||
case 'unclaimed_rewards':
|
||||
return 'operatorReward';
|
||||
case 'profit_margin_percent':
|
||||
return 'profitMarginValue';
|
||||
case 'operating_cost':
|
||||
return 'operatorCostValue';
|
||||
default:
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
const mapAndSort = (_items: TDelegations) => {
|
||||
const mapToNumberType = _items.map((item) =>
|
||||
isDelegation(item)
|
||||
? {
|
||||
...item,
|
||||
delegationValue: Number(item.amount.amount),
|
||||
operatorReward: Number(item.unclaimed_rewards?.amount),
|
||||
profitMarginValue: Number(item.cost_params?.profit_margin_percent),
|
||||
operatorCostValue: Number(item.cost_params?.interval_operating_cost.amount),
|
||||
}
|
||||
: item,
|
||||
);
|
||||
const ordered = _orderBy(mapToNumberType, mapOrderBy(orderBy), order).sort();
|
||||
return ordered;
|
||||
};
|
||||
|
||||
return [...unbondedDelegations, ...mapAndSort(delegations)];
|
||||
};
|
||||
Reference in New Issue
Block a user