Parachain approval (#4374)

* Parachain approval

* trigger date
This commit is contained in:
Jaco Greeff 2021-01-12 10:50:04 +01:00 committed by GitHub
parent 1c615f40b3
commit 4b0335533a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 15 deletions

View File

@ -21,7 +21,7 @@ function Actions (): React.ReactElement<Props> {
return (
<>
<Button.Group>
{api.query.proposeParachains && (
{api.query.proposeParachain && (
<Button
icon='plus'
isDisabled={true}

View File

@ -5,10 +5,12 @@ import type { ProposalExt } from './types';
import React, { useMemo } from 'react';
import { AddressMini, AddressSmall, Badge } from '@polkadot/react-components';
import { AddressMini, AddressSmall, Badge, TxButton } from '@polkadot/react-components';
import { useApi, useSudo } from '@polkadot/react-hooks';
import { FormatBalance } from '@polkadot/react-query';
import { formatNumber } from '@polkadot/util';
import { useTranslation } from '../translate';
import { sliceHex } from './util';
interface Props {
@ -16,6 +18,10 @@ interface Props {
}
function Proposal ({ proposal: { id, isApproved, proposal: { balance, genesisHead, name, proposer, validationCode, validators } } }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const { hasSudoKey, sudoKey } = useSudo();
const initialHex = useMemo(
() => sliceHex(genesisHead, 8),
[genesisHead]
@ -48,6 +54,18 @@ function Proposal ({ proposal: { id, isApproved, proposal: { balance, genesisHea
value={validatorId}
/>
))}</td>
<td className='button'>
{!isApproved && (
<TxButton
accountId={sudoKey}
icon='check'
isDisabled={!hasSudoKey}
label={t<string>('Approve')}
params={[id]}
tx={api.tx.proposeParachain?.approveProposal}
/>
)}
</td>
</tr>
);
}

View File

@ -24,7 +24,8 @@ function Proposals ({ proposals }: Props): React.ReactElement<Props> {
[t('balance')],
[t('initial state'), 'start'],
[t('validation'), 'start'],
[t('validators'), 'address']
[t('validators'), 'address'],
[]
]);
return (

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { Option } from '@polkadot/types';
import type { ParachainProposal, ParaId } from '@polkadot/types/interfaces';
import type { EventRecord, ParachainProposal, ParaId } from '@polkadot/types/interfaces';
import type { ProposalExt } from './types';
import { useEffect, useState } from 'react';
@ -23,16 +23,28 @@ export default function useProposals (): ProposalExt[] | undefined {
const { api } = useApi();
const mountedRef = useIsMountedRef();
const [state, setState] = useState<ProposalExt[] | undefined>();
const approvedIds = useCall<ParaId[]>(api.query.proposeParachains?.approvedProposals);
const [trigger, setTrigger] = useState(Date.now());
const approvedIds = useCall<ParaId[]>(api.query.proposeParachain?.approvedProposals);
const events = useCall<EventRecord[]>(api.query.system.events);
// trigger on any proposeParachain events
useEffect((): void => {
approvedIds && api.query.proposeParachain.proposals
mountedRef.current && events && setTrigger((trigger) =>
events.filter(({ event: { section }, phase }) => phase.isApplyExtrinsic && section === 'proposeParachain').length
? Date.now()
: trigger
);
}, [events, mountedRef]);
// re-get all our entries in the list
useEffect((): void => {
approvedIds && trigger && api.query.proposeParachain.proposals
.entries()
.then((entries) =>
mountedRef.current && setState(createExt(approvedIds, entries as any))
)
.catch(console.error);
}, [api, approvedIds, mountedRef]);
}, [api, approvedIds, mountedRef, trigger]);
return state;
}

View File

@ -15,7 +15,7 @@ import { useTranslation } from './translate';
function SudoApp ({ basePath }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { allAccounts, isMine, sudoKey } = useSudo();
const { allAccounts, hasSudoKey, sudoKey } = useSudo();
const itemsRef = useRef([
{
@ -37,20 +37,20 @@ function SudoApp ({ basePath }: Props): React.ReactElement<Props> {
items={itemsRef.current}
/>
</header>
{isMine
{hasSudoKey
? (
<Switch>
<Route path={`${basePath}/key`}>
<SetKey
allAccounts={allAccounts}
isMine={isMine}
isMine={hasSudoKey}
sudoKey={sudoKey}
/>
</Route>
<Route>
<Sudo
allAccounts={allAccounts}
isMine={isMine}
isMine={hasSudoKey}
sudoKey={sudoKey}
/>
</Route>

View File

@ -74,8 +74,8 @@ export interface TxState extends ExtrinsicAndSenders {
export interface UseSudo {
allAccounts: string[];
hasSudoKey: boolean;
sudoKey?: string;
isMine: boolean;
}
export interface AddressFlags extends DeriveAccountFlags {

View File

@ -18,11 +18,11 @@ export function useSudo (): UseSudo {
const { api } = useApi();
const { allAccounts, hasAccounts } = useAccounts();
const sudoKey = useCall<string>(hasAccounts && api.query.sudo?.key, undefined, transformSudo);
const [isMine, setIsMine] = useState(false);
const [hasSudoKey, setHasSudoKey] = useState(false);
useEffect((): void => {
setIsMine(!!sudoKey && !!allAccounts && allAccounts.some((key) => key === sudoKey));
setHasSudoKey(!!sudoKey && !!allAccounts && allAccounts.some((key) => key === sudoKey));
}, [allAccounts, sudoKey]);
return { allAccounts, isMine, sudoKey };
return { allAccounts, hasSudoKey, sudoKey };
}