Allow sorting of staking returns (#2183)
This commit is contained in:
parent
fbcdac2890
commit
58e3dab9bc
@ -43,10 +43,10 @@ export default function Validator ({ info: { accountId, bondOther, bondOwn, bond
|
||||
: <FormatBalance label={<label>{t('commission')}</label>} value={validatorPayment} />
|
||||
}
|
||||
</td>
|
||||
<td className='number'><FormatBalance label={<label>{t('total stake')}</label>} value={bondTotal} /></td>
|
||||
<td className='number'><FormatBalance label={<label>{t('own stake')}</label>} value={bondOwn} /></td>
|
||||
<td className='number'><FormatBalance label={<label>{t('other stake')}</label>} value={bondOther} > ({formatNumber(numNominators)})</FormatBalance></td>
|
||||
<td className='number'><FormatBalance label={<label>{t('payout (est.)')}</label>} value={rewardPayout} /></td>
|
||||
<td className='number together'><FormatBalance label={<label>{t('total stake')}</label>} value={bondTotal} /></td>
|
||||
<td className='number together'><FormatBalance label={<label>{t('own stake')}</label>} value={bondOwn} /></td>
|
||||
<td className='number together'><FormatBalance label={<label>{t('other stake')}</label>} value={bondOther} > ({formatNumber(numNominators)})</FormatBalance></td>
|
||||
<td className='number together'><FormatBalance label={<label>{t('payout (est.)')}</label>} value={rewardPayout} /></td>
|
||||
<td>
|
||||
<Icon
|
||||
className='staking--stats'
|
||||
|
||||
@ -11,7 +11,7 @@ import BN from 'bn.js';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { registry } from '@polkadot/react-api';
|
||||
import { InputBalance, Table } from '@polkadot/react-components';
|
||||
import { Icon, InputBalance, Table } from '@polkadot/react-components';
|
||||
import { useAccounts, useApi, useDebounce, useFavorites, useCall } from '@polkadot/react-hooks';
|
||||
import { createType } from '@polkadot/types';
|
||||
|
||||
@ -32,11 +32,31 @@ interface AllInfo {
|
||||
validators: ValidatorInfo[];
|
||||
}
|
||||
|
||||
type SortBy = 'rankOverall' | 'rankBondOwn' | 'rankBondOther' | 'rankBondTotal' | 'rankComm';
|
||||
|
||||
function sortValidators (list: ValidatorInfo[]): ValidatorInfo[] {
|
||||
return list
|
||||
.sort((a, b): number => b.commissionPer - a.commissionPer)
|
||||
.map((info, index): ValidatorInfo => {
|
||||
info.rankComm = index + 1;
|
||||
|
||||
return info;
|
||||
})
|
||||
.sort((a, b): number => b.bondOther.cmp(a.bondOther))
|
||||
.map((info, index): ValidatorInfo => {
|
||||
info.rankBondOther = index + 1;
|
||||
|
||||
return info;
|
||||
})
|
||||
.sort((a, b): number => b.bondOwn.cmp(a.bondOwn))
|
||||
.map((info, index): ValidatorInfo => {
|
||||
info.rankBondOwn = index + 1;
|
||||
|
||||
return info;
|
||||
})
|
||||
.sort((a, b): number => b.bondTotal.cmp(a.bondTotal))
|
||||
.map((info, index): ValidatorInfo => {
|
||||
info.rankBonded = index + 1;
|
||||
info.rankBondTotal = index + 1;
|
||||
|
||||
return info;
|
||||
})
|
||||
@ -59,30 +79,15 @@ function sortValidators (list: ValidatorInfo[]): ValidatorInfo[] {
|
||||
? cmp
|
||||
: a.rankReward === b.rankReward
|
||||
? a.rankPayment === b.rankPayment
|
||||
? a.rankBonded === b.rankBonded
|
||||
? 0
|
||||
: a.rankBonded < b.rankBonded
|
||||
? 1
|
||||
: -1
|
||||
: a.rankPayment < b.rankPayment
|
||||
? 1
|
||||
: -1
|
||||
: a.rankReward < b.rankReward
|
||||
? 1
|
||||
: -1;
|
||||
? b.rankBondTotal - a.rankBondTotal
|
||||
: b.rankPayment - a.rankPayment
|
||||
: b.rankReward - a.rankReward;
|
||||
})
|
||||
.map((info, index): ValidatorInfo => {
|
||||
info.rankOverall = index + 1;
|
||||
|
||||
return info;
|
||||
})
|
||||
.sort((a, b): number =>
|
||||
a.isFavorite === b.isFavorite
|
||||
? 0
|
||||
: a.isFavorite
|
||||
? -1
|
||||
: 1
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function extractInfo (allAccounts: string[], amount: BN = new BN(0), electedInfo: DerivedStakingElected, favorites: string[], lastReward: BN): AllInfo {
|
||||
@ -126,7 +131,10 @@ function extractInfo (allAccounts: string[], amount: BN = new BN(0), electedInfo
|
||||
key,
|
||||
commissionPer: (((prefs as ValidatorPrefs).commission?.unwrap() || new BN(0)).muln(10000).div(PERBILL).toNumber() / 100),
|
||||
numNominators: exposure.others.length,
|
||||
rankBonded: 0,
|
||||
rankBondOther: 0,
|
||||
rankBondOwn: 0,
|
||||
rankBondTotal: 0,
|
||||
rankComm: 0,
|
||||
rankOverall: 0,
|
||||
rankPayment: 0,
|
||||
rankReward: 0,
|
||||
@ -149,8 +157,31 @@ function Targets ({ className, sessionRewards }: Props): React.ReactElement<Prop
|
||||
const [favorites, toggleFavorite] = useFavorites(STORE_FAVS_BASE);
|
||||
const [lastReward, setLastReward] = useState(new BN(0));
|
||||
const [{ validators, totalStaked }, setWorkable] = useState<AllInfo>({ totalStaked: new BN(0), validators: [] });
|
||||
const [{ sorted, sortBy, sortFromMax }, setSorted] = useState<{ sorted: ValidatorInfo[]; sortBy: SortBy; sortFromMax: boolean }>({ sorted: [], sortBy: 'rankOverall', sortFromMax: true });
|
||||
const amount = useDebounce(_amount);
|
||||
|
||||
const _sort = (newSortBy: SortBy, unsorted = validators, isAdjust = true): void => {
|
||||
const newSortFromMax = isAdjust && newSortBy === sortBy ? !sortFromMax : true;
|
||||
|
||||
setSorted({
|
||||
sortBy: newSortBy,
|
||||
sortFromMax: newSortFromMax,
|
||||
sorted: unsorted
|
||||
.sort((a, b): number =>
|
||||
newSortFromMax
|
||||
? a[newSortBy] - b[newSortBy]
|
||||
: b[newSortBy] - a[newSortBy]
|
||||
)
|
||||
.sort((a, b): number =>
|
||||
a.isFavorite === b.isFavorite
|
||||
? 0
|
||||
: a.isFavorite
|
||||
? -1
|
||||
: 1
|
||||
)
|
||||
});
|
||||
};
|
||||
|
||||
useEffect((): void => {
|
||||
if (sessionRewards && sessionRewards.length) {
|
||||
const lastRewardSession = sessionRewards.filter(({ reward }): boolean => reward.gtn(0));
|
||||
@ -165,17 +196,22 @@ function Targets ({ className, sessionRewards }: Props): React.ReactElement<Prop
|
||||
|
||||
useEffect((): void => {
|
||||
if (electedInfo) {
|
||||
setWorkable(extractInfo(allAccounts, amount, electedInfo, favorites, lastReward));
|
||||
const { totalStaked, validators } = extractInfo(allAccounts, amount, electedInfo, favorites, lastReward);
|
||||
|
||||
setWorkable({ totalStaked, validators });
|
||||
_sort('rankOverall', validators, false);
|
||||
}
|
||||
}, [allAccounts, amount, electedInfo, favorites, lastReward]);
|
||||
|
||||
const sortIcon = `chevron ${sortFromMax ? 'down' : 'up'}` as 'chevron up';
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<Summary
|
||||
lastReward={lastReward}
|
||||
totalStaked={totalStaked}
|
||||
/>
|
||||
{validators.length
|
||||
{sorted.length
|
||||
? (
|
||||
<>
|
||||
<InputBalance
|
||||
@ -187,8 +223,21 @@ function Targets ({ className, sessionRewards }: Props): React.ReactElement<Prop
|
||||
value={_amount}
|
||||
/>
|
||||
<Table>
|
||||
<Table.Head>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
{['rankComm', 'rankBondTotal', 'rankBondOwn', 'rankBondOther', 'rankOverall'].map((header): React.ReactNode => (
|
||||
<th
|
||||
className={`isClickable ${sortBy === header && 'isSelected'}`}
|
||||
key={header}
|
||||
onClick={(): void => _sort(header as 'rankComm')}
|
||||
>{sortBy === header ? <Icon name={sortIcon} /> : ''}</th>
|
||||
))}
|
||||
<th> </th>
|
||||
</Table.Head>
|
||||
<Table.Body>
|
||||
{validators.map((info): React.ReactNode =>
|
||||
{sorted.map((info): React.ReactNode =>
|
||||
<Validator
|
||||
info={info}
|
||||
key={info.key}
|
||||
|
||||
@ -18,7 +18,10 @@ export interface ValidatorInfo {
|
||||
isNominating: boolean;
|
||||
key: string;
|
||||
numNominators: number;
|
||||
rankBonded: number;
|
||||
rankBondOther: number;
|
||||
rankBondOwn: number;
|
||||
rankBondTotal: number;
|
||||
rankComm: number;
|
||||
rankOverall: number;
|
||||
rankPayment: number;
|
||||
rankReward: number;
|
||||
|
||||
@ -101,7 +101,7 @@ export default styled(Table)`
|
||||
}
|
||||
|
||||
td, th {
|
||||
text-align: left;
|
||||
padding: 0.5rem 0.75rem;
|
||||
|
||||
&.all {
|
||||
width: 100%;
|
||||
@ -146,7 +146,8 @@ export default styled(Table)`
|
||||
border: 1px solid #f2f2f2;
|
||||
border-left-width: 0;
|
||||
border-right-width: 0;
|
||||
padding: 0.5rem 0.75rem;
|
||||
|
||||
text-align: left;
|
||||
|
||||
label {
|
||||
display: block !important;
|
||||
@ -181,7 +182,7 @@ export default styled(Table)`
|
||||
color: #eee;
|
||||
font-family: sans-serif;
|
||||
font-weight: normal;
|
||||
padding: 0.75rem;
|
||||
text-align: right;
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: 0.25rem;
|
||||
@ -190,6 +191,14 @@ export default styled(Table)`
|
||||
&:last-child {
|
||||
border-top-right-radius: 0.25rem;
|
||||
}
|
||||
|
||||
&.isClickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.isSelected {
|
||||
background: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user