Referendum passing status (#2447)

* Referendum passing status

* WarmUp totalIssuance

* Optional balances
This commit is contained in:
Jaco Greeff 2020-03-23 19:55:17 +01:00 committed by GitHub
parent 19ac852c8d
commit 39759950ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 4 deletions

View File

@ -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 (

View File

@ -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

View 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;
}