From cd6d6a34e1c0ca2886b9522c816220eaf1670162 Mon Sep 17 00:00:00 2001 From: Jaco Date: Thu, 20 May 2021 07:34:08 +0300 Subject: [PATCH] Display Multisig approvals (#5323) * Display Multisig approvals * label --- .../src/modals/MultisigApprove.tsx | 77 ++++++++++++++----- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/packages/page-accounts/src/modals/MultisigApprove.tsx b/packages/page-accounts/src/modals/MultisigApprove.tsx index 67cc37d26b..bdd8d03ebc 100644 --- a/packages/page-accounts/src/modals/MultisigApprove.tsx +++ b/packages/page-accounts/src/modals/MultisigApprove.tsx @@ -4,10 +4,10 @@ import type { SubmittableExtrinsic } from '@polkadot/api/types'; import type { AccountId, Call, H256, Multisig } from '@polkadot/types/interfaces'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import styled from 'styled-components'; -import { Dropdown, Input, InputAddress, Modal, Toggle, TxButton } from '@polkadot/react-components'; +import { AddressMini, Dropdown, Expander, Input, InputAddress, MarkError, Modal, Toggle, TxButton } from '@polkadot/react-components'; import { useAccounts, useApi, useWeight } from '@polkadot/react-hooks'; import { assert, isHex } from '@polkadot/util'; @@ -32,11 +32,18 @@ interface Option { value: string; } +interface CallData { + callData: Call | null; + callError: string | null; +} + +const EMPTY_CALL: CallData = { callData: null, callError: null }; + function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }: Props): React.ReactElement { const { t } = useTranslation(); const { api } = useApi(); const { allAccounts } = useAccounts(); - const [callData, setCallData] = useState(null); + const [{ callData, callError }, setCallData] = useState(EMPTY_CALL); const [callWeight] = useWeight(callData); const [hash, setHash] = useState(ongoing[0][0].toHex()); const [{ isMultiCall, multisig }, setMultisig] = useState({ isMultiCall: false, multisig: null }); @@ -46,13 +53,12 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }: const [whoFilter, setWhoFilter] = useState([]); const [type, setType] = useState('aye'); const [tx, setTx] = useState | null>(null); - const calltypes = useMemo( - () => [ - { text: t('Approve this call hash'), value: 'aye' }, - { text: t('Cancel this call hash'), value: 'nay' } - ], - [t] - ); + + const callOptRef = useRef([ + { text: t('Approve this call hash'), value: 'aye' }, + { text: t('Cancel this call hash'), value: 'nay' } + ]); + const hashes = useMemo( () => ongoing.map(([h]) => ({ text: h.toHex(), value: h.toHex() })), [ongoing] @@ -66,7 +72,7 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }: isMultiCall: !!multisig && (multisig.approvals.length + 1) >= threshold, multisig }); - setCallData(null); + setCallData(EMPTY_CALL); }, [hash, ongoing, threshold]); // the others are all the who elements, without the current signatory (re-encoded) @@ -128,13 +134,11 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }: const callData = api.createType('Call', callHex); - setCallData( - callData.hash.eq(hash) - ? callData - : null - ); + assert(callData.hash.eq(hash), 'Call data does not match the existing call hash'); + + setCallData({ callData, callError: null }); } catch (error) { - setCallData(null); + setCallData({ callData: null, callError: (error as Error).message }); } }, [api, hash] @@ -152,18 +156,50 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }: ('The call hashes that have not been executed as of yet.')} - label={t('pending hashes')} + label={t('pending hashes {{count}}', { + replace: { count: hashes.length } + })} onChange={setHash} options={hashes} value={hash} /> + {multisig && ( + <> + ('The creator for this multisig call')}> + ('depositor')} + /> + + ('The current approvals applied to this multisig')}> + ('Existing approvals ({{approvals}}/{{threshold}})', { + replace: { + approvals: multisig.approvals.length, + threshold + } + })} + > + {multisig.approvals.map((a) => + + )} + + + + )} ('Either approve or reject this call.')} label={t('approval type')} onChange={setType} - options={calltypes} + options={callOptRef.current} value={type} /> @@ -188,6 +224,9 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }: label={t('call data for final approval')} onChange={_setCallData} /> + {callError && ( + + )} )}