Referendum passing status (#2447)
* Referendum passing status * WarmUp totalIssuance * Optional balances
This commit is contained in:
parent
19ac852c8d
commit
39759950ce
@ -11,10 +11,11 @@ function WarmUp (): React.ReactElement {
|
||||
const indexes = useCall<unknown>(isApiReady && api.derive.accounts?.indexes, []);
|
||||
const registrars = useCall<unknown>(isApiReady && api.query.identity?.registrars, []);
|
||||
const staking = null; // useCall<unknown>(isApiReady && api.derive.staking?.overview, []);
|
||||
const issuance = useCall<unknown>(isApiReady && api.query.balances?.totalIssuance, []);
|
||||
const [hasValues, setHasValues] = useState(false);
|
||||
|
||||
useEffect((): void => {
|
||||
setHasValues(!!fees || !!indexes || !!registrars || !!staking);
|
||||
setHasValues(!!fees || !!indexes || !!issuance || !!registrars || !!staking);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@ -5,17 +5,18 @@
|
||||
import { DerivedReferendum } from '@polkadot/api-derive/types';
|
||||
import { BlockNumber } from '@polkadot/types/interfaces';
|
||||
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { AddressMini, Button, Expander, LinkExternal } from '@polkadot/react-components';
|
||||
import { AddressMini, Badge, Button, Expander, Icon, LinkExternal } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { FormatBalance, BlockToTime } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
import { formatNumber, isBoolean } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import PreImageButton from './PreImageButton';
|
||||
import ProposalCell from './ProposalCell';
|
||||
import Voting from './Voting';
|
||||
import useIsPassing from './useIsPassing';
|
||||
import useVotes from './useVotes';
|
||||
|
||||
interface Props {
|
||||
@ -27,7 +28,12 @@ function Referendum ({ className, value }: Props): React.ReactElement<Props> | n
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []);
|
||||
const isPassing = useIsPassing(value);
|
||||
const { allAye, allNay, voteCountAye, voteCountNay, votedAye, votedNay } = useVotes(value);
|
||||
const threshold = useMemo(
|
||||
() => value.status.threshold.type.toString().replace('majority', ' majority '),
|
||||
[value]
|
||||
);
|
||||
|
||||
if (!bestNumber || value.status.end.sub(bestNumber).lten(0)) {
|
||||
return null;
|
||||
@ -76,6 +82,17 @@ function Referendum ({ className, value }: Props): React.ReactElement<Props> | n
|
||||
)}
|
||||
</Expander>
|
||||
</td>
|
||||
<td className='padtop top'>
|
||||
{isBoolean(isPassing) && (
|
||||
<Badge
|
||||
hover={isPassing ? t('{{threshold}}, passing', { replace: { threshold } }) : t('{{threshold}}, not passing', { replace: { threshold } })}
|
||||
info={<Icon name={isPassing ? 'check' : 'cancel'} />}
|
||||
isInline
|
||||
isTooltip
|
||||
type={isPassing ? 'green' : 'brown'}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='number together top'>
|
||||
<Button.Group>
|
||||
<Voting
|
||||
|
||||
65
packages/page-democracy/src/Overview/useIsPassing.ts
Normal file
65
packages/page-democracy/src/Overview/useIsPassing.ts
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2017-2020 @polkadot/app-democracy authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { DerivedReferendum } from '@polkadot/api-derive/types';
|
||||
import { ReferendumStatus } from '@polkadot/types/interfaces';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
function compareRationals (n1: BN, d1: BN, n2: BN, d2: BN): boolean {
|
||||
while (true) {
|
||||
const q1 = n1.div(d1);
|
||||
const q2 = n2.div(d2);
|
||||
|
||||
if (q1.lt(q2)) {
|
||||
return true;
|
||||
} else if (q2.lt(q1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const r1 = n1.mod(d1);
|
||||
const r2 = n2.mod(d2);
|
||||
|
||||
if (r2.isZero()) {
|
||||
return false;
|
||||
} else if (r1.isZero()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
n1 = d2;
|
||||
n2 = d1;
|
||||
d1 = r2;
|
||||
d2 = r1;
|
||||
}
|
||||
}
|
||||
|
||||
export default function useIsPassing (referendum: DerivedReferendum): boolean | undefined {
|
||||
const { api } = useApi();
|
||||
const totalIssuance = useCall<BN>(api.query.balances.totalIssuance, []);
|
||||
const [isPassing, setIsPassing] = useState<boolean | undefined>(undefined);
|
||||
|
||||
useEffect((): void => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
const { tally, threshold } = (referendum.status as ReferendumStatus);
|
||||
|
||||
if (totalIssuance && tally) {
|
||||
const sqrtVoters = tally.turnout.toRed(BN.red('k256')).redSqrt().fromRed();
|
||||
const sqrtElectorate = totalIssuance.toRed(BN.red('k256')).redSqrt().fromRed();
|
||||
|
||||
setIsPassing(
|
||||
sqrtVoters.isZero()
|
||||
? false
|
||||
: threshold.isSimplemajority
|
||||
? tally.ayes.gt(tally.nays)
|
||||
: threshold.isSupermajorityapproval
|
||||
? compareRationals(tally.nays, sqrtVoters, tally.ayes, sqrtElectorate)
|
||||
: compareRationals(tally.nays, sqrtElectorate, tally.ayes, sqrtVoters)
|
||||
);
|
||||
}
|
||||
}, [referendum, totalIssuance]);
|
||||
|
||||
return isPassing;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user