diff --git a/packages/page-council/src/Motions/ProposeExternal.tsx b/packages/page-council/src/Motions/ProposeExternal.tsx index ff2afefbde..cafb735c26 100644 --- a/packages/page-council/src/Motions/ProposeExternal.tsx +++ b/packages/page-council/src/Motions/ProposeExternal.tsx @@ -10,7 +10,7 @@ import { useApi, useToggle } from '@polkadot/react-hooks'; import { isHex } from '@polkadot/util'; import { useTranslation } from '../translate'; -import { getThreshold } from './thresholds'; +import { getThreshold } from '../thresholds'; interface Props { className?: string; @@ -35,6 +35,7 @@ function ProposeExternal ({ className = '', isMember, members }: Props): React.R const [accountId, setAcountId] = useState(null); const [{ proposal, proposalLength }, setProposal] = useState({ proposalLength: 0 }); const [{ hash, isHashValid }, setHash] = useState({ hash: '', isHashValid: false }); + const threshold = Math.ceil((members.length || 0) * getThreshold(api)); const _onChangeHash = useCallback( diff --git a/packages/page-council/src/Motions/ProposeMotion.tsx b/packages/page-council/src/Motions/ProposeMotion.tsx index ffe6bbf0d2..7c4851066c 100644 --- a/packages/page-council/src/Motions/ProposeMotion.tsx +++ b/packages/page-council/src/Motions/ProposeMotion.tsx @@ -11,7 +11,7 @@ import { useApi, useToggle } from '@polkadot/react-hooks'; import { BN_ZERO } from '@polkadot/util'; import { useTranslation } from '../translate'; -import { getThreshold } from './thresholds'; +import { getThreshold } from '../thresholds'; interface Props { isMember: boolean; diff --git a/packages/page-council/src/Motions/Slashing.tsx b/packages/page-council/src/Motions/Slashing.tsx index 7c21130439..f32d44f085 100644 --- a/packages/page-council/src/Motions/Slashing.tsx +++ b/packages/page-council/src/Motions/Slashing.tsx @@ -9,7 +9,7 @@ import { Button, Dropdown, Input, InputAddress, Modal, TxButton } from '@polkado import { useApi, useAvailableSlashes, useToggle } from '@polkadot/react-hooks'; import { useTranslation } from '../translate'; -import { getSlashThreshold } from './thresholds'; +import { getSlashThreshold } from '../thresholds'; interface Props { className?: string; @@ -36,6 +36,7 @@ function Slashing ({ className = '', isMember, members }: Props): React.ReactEle const [{ proposal, proposalLength }, setProposal] = useState({ proposal: null, proposalLength: 0 }); const [eras, setEras] = useState([]); const [selectedEra, setSelectedEra] = useState(0); + const threshold = Math.ceil((members.length || 0) * getSlashThreshold(api)); useEffect((): void => { diff --git a/packages/page-council/src/Motions/thresholds.ts b/packages/page-council/src/thresholds.ts similarity index 76% rename from packages/page-council/src/Motions/thresholds.ts rename to packages/page-council/src/thresholds.ts index b252e3750f..d947ec7261 100644 --- a/packages/page-council/src/Motions/thresholds.ts +++ b/packages/page-council/src/thresholds.ts @@ -15,6 +15,11 @@ const SLASH_THRESHOLDS: Record = { [POLKADOT_GENESIS]: 0.75 }; +const TREASURY_THRESHOLDS: Record = { + // Polkadot + [POLKADOT_GENESIS]: 0.6 +}; + export function getThreshold (api: ApiPromise): number { return PROPOSE_THRESHOLDS[api.genesisHash.toHex()] || 0.5; } @@ -22,3 +27,7 @@ export function getThreshold (api: ApiPromise): number { export function getSlashThreshold (api: ApiPromise): number { return SLASH_THRESHOLDS[api.genesisHash.toHex()] || 0.5; } + +export function getTreasuryThreshold (api: ApiPromise): number { + return TREASURY_THRESHOLDS[api.genesisHash.toHex()] || 0.6; +} diff --git a/packages/page-treasury/src/Overview/ProposalCreate.tsx b/packages/page-treasury/src/Overview/ProposalCreate.tsx index 772671d3ba..4234d65d9b 100644 --- a/packages/page-treasury/src/Overview/ProposalCreate.tsx +++ b/packages/page-treasury/src/Overview/ProposalCreate.tsx @@ -21,6 +21,7 @@ function Propose ({ className }: Props): React.ReactElement | null { const [isOpen, toggleOpen] = useToggle(); const [value, setValue] = useState(); const hasValue = value?.gtn(0); + const bondPercentage = useMemo( () => `${api.consts.treasury.proposalBond.muln(100).divn(1_000_000).toNumber().toFixed(2)}%`, [api] diff --git a/packages/page-treasury/src/Overview/Submission.tsx b/packages/page-treasury/src/Overview/Submission.tsx index 7b29f3aad3..2411282c6e 100644 --- a/packages/page-treasury/src/Overview/Submission.tsx +++ b/packages/page-treasury/src/Overview/Submission.tsx @@ -7,8 +7,9 @@ import { DeriveCollectiveProposal } from '@polkadot/api-derive/types'; import { ProposalIndex } from '@polkadot/types/interfaces'; import React, { useEffect, useMemo, useState } from 'react'; +import { getTreasuryThreshold } from '@polkadot/app-council/thresholds'; import { Button, Dropdown, InputAddress, Modal, TxButton } from '@polkadot/react-components'; -import { useApi, useCall, useToggle } from '@polkadot/react-hooks'; +import { useApi, useToggle } from '@polkadot/react-hooks'; import { useTranslation } from '../translate'; @@ -27,15 +28,14 @@ interface ProposalState { function Submission ({ councilProposals, id, isDisabled, members }: Props): React.ReactElement | null { const { t } = useTranslation(); const { api } = useApi(); - const councilThreshold = useCall((api.query.electionsPhragmen || api.query.elections).members, [], { - transform: (value: unknown[]): number => - Math.ceil(value.length * 0.6) - }); const [isOpen, toggleOpen] = useToggle(); const [accountId, setAccountId] = useState(null); const [councilType, setCouncilType] = useState('reject'); const [{ proposal, proposalLength }, setProposal] = useState({ proposalLength: 0 }); const [hasProposals, setHasProposals] = useState(true); + + const threshold = Math.ceil((members?.length || 0) * getTreasuryThreshold(api)); + const councilTypeOpt = useMemo(() => [ { text: t('Acceptance proposal to council'), value: 'accept' }, { text: t('Rejection proposal to council'), value: 'reject' } @@ -104,13 +104,13 @@ function Submission ({ councilProposals, id, isDisabled, members }: Props): Reac ('Send to council')} onStart={toggleOpen} params={ api.tx.council.propose.meta.args.length === 3 - ? [councilThreshold, proposal, proposalLength] - : [councilThreshold, proposal] + ? [threshold, proposal, proposalLength] + : [threshold, proposal] } tx='council.propose' /> diff --git a/packages/react-hooks/src/useMembers.ts b/packages/react-hooks/src/useMembers.ts index 19ca6e72e2..2b19d7895a 100644 --- a/packages/react-hooks/src/useMembers.ts +++ b/packages/react-hooks/src/useMembers.ts @@ -4,7 +4,7 @@ import { AccountId } from '@polkadot/types/interfaces'; -import { useEffect, useState } from 'react'; +import { useMemo } from 'react'; import { useAccounts, useApi, useCall } from '@polkadot/react-hooks'; interface Result { @@ -15,17 +15,16 @@ interface Result { export default function useMembers (collective: 'council' | 'technicalCommittee' = 'council'): Result { const { api } = useApi(); const { allAccounts, hasAccounts } = useAccounts(); - const [state, setState] = useState({ isMember: false, members: [] }); const retrieved = useCall(hasAccounts && api.query[collective]?.members, [], { - transform: (accounts: AccountId[]) => accounts.map((accountId) => accountId.toString()) + transform: (accounts: AccountId[]) => + accounts.map((accountId) => accountId.toString()) }); - useEffect((): void => { - retrieved && setState({ - isMember: retrieved.some((accountId) => allAccounts.includes(accountId)), - members: retrieved - }); - }, [allAccounts, retrieved]); - - return state; + return useMemo( + () => ({ + isMember: (retrieved || []).some((accountId) => allAccounts.includes(accountId)), + members: (retrieved || []) + }), + [allAccounts, retrieved] + ); }