Show proxied with no accounts (#2959)
* Display proxied with no local attached * Allow anybody to submit call on final * Proxy indicator
This commit is contained in:
parent
66cee9a03c
commit
5374a784f4
@ -29,6 +29,7 @@ import RecoverAccount from './modals/RecoverAccount';
|
||||
import RecoverSetup from './modals/RecoverSetup';
|
||||
import Transfer from './modals/Transfer';
|
||||
import useMultisigApprovals from './useMultisigApprovals';
|
||||
import useProxies from './useProxies';
|
||||
|
||||
interface Props extends SortedAccount {
|
||||
className?: string;
|
||||
@ -73,7 +74,8 @@ function Account ({ account: { address, meta }, className = '', filter, isFavori
|
||||
transform: (opt: Option<RecoveryConfig>) => opt.unwrapOr(null)
|
||||
});
|
||||
const multiInfos = useMultisigApprovals(address);
|
||||
const { flags: { isDevelopment, isExternal, isHardware, isInjected, isMultisig }, genesisHash, name: accName, onSetGenesisHash, tags } = useAccountInfo(address);
|
||||
const proxyInfo = useProxies(address);
|
||||
const { flags: { isDevelopment, isExternal, isHardware, isInjected, isMultisig, isProxied }, genesisHash, name: accName, onSetGenesisHash, tags } = useAccountInfo(address);
|
||||
const [{ democracyUnlockTx }, setUnlockableIds] = useState<DemocracyUnlockable>({ democracyUnlockTx: null, ids: [] });
|
||||
const [isVisible, setIsVisible] = useState(true);
|
||||
const [isBackupOpen, toggleBackup] = useToggle();
|
||||
@ -227,6 +229,15 @@ function Account ({ account: { address, meta }, className = '', filter, isFavori
|
||||
type='brown'
|
||||
/>
|
||||
)}
|
||||
{isProxied && !proxyInfo.hasOwned && (
|
||||
<Badge
|
||||
hover={t<string>('Proxied account has no owned proxies')}
|
||||
info='0'
|
||||
isInline
|
||||
isTooltip
|
||||
type='brown'
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='address'>
|
||||
<AddressSmall value={address} />
|
||||
|
||||
@ -240,7 +240,6 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen
|
||||
footer={footer}
|
||||
header={header}
|
||||
>
|
||||
{}
|
||||
{sortedAccounts.map(({ account, isFavorite }): React.ReactNode => (
|
||||
<Account
|
||||
account={account}
|
||||
|
||||
@ -78,19 +78,22 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }:
|
||||
);
|
||||
}, [signatory, who]);
|
||||
|
||||
// filter the who by those not approved yet that is an actual account we own. In the case of
|
||||
// Filter the who by those not approved yet that is an actual account we own. In the case of
|
||||
// rejections, we defer to the the first approver, since he is the only one to send the cancel
|
||||
// On reaching threshold, we include all possible signatories in the list
|
||||
useEffect((): void => {
|
||||
const hasThreshold = multisig && (multisig.approvals.length >= threshold);
|
||||
|
||||
setWhoFilter(
|
||||
who
|
||||
.map((w) => registry.createType('AccountId', w).toString())
|
||||
.filter((w) => allAccounts.some((a) => a === w) && multisig && (
|
||||
type === 'nay'
|
||||
? multisig.approvals[0].eq(w)
|
||||
: !multisig.approvals.some((a) => a.eq(w))
|
||||
: hasThreshold || !multisig.approvals.some((a) => a.eq(w))
|
||||
))
|
||||
);
|
||||
}, [allAccounts, multisig, type, who]);
|
||||
}, [allAccounts, multisig, threshold, type, who]);
|
||||
|
||||
// based on the type, multisig, others create the tx. This can be either an approval or final call
|
||||
useEffect((): void => {
|
||||
|
||||
@ -2,16 +2,16 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ProxyType } from '@polkadot/types/interfaces';
|
||||
import { ActionStatus } from '@polkadot/react-components/Status/types';
|
||||
import { ModalProps } from '../../types';
|
||||
|
||||
import React, { useCallback, useState, useEffect } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { Button, Input, InputAddressSimple, Modal } from '@polkadot/react-components';
|
||||
import { useAccounts, useApi } from '@polkadot/react-hooks';
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
import keyring from '@polkadot/ui-keyring';
|
||||
|
||||
import { useTranslation } from '../../translate';
|
||||
import useProxies from '../useProxies';
|
||||
|
||||
interface Props extends ModalProps {
|
||||
className?: string;
|
||||
@ -24,17 +24,6 @@ interface CreateOptions {
|
||||
tags?: string[];
|
||||
}
|
||||
|
||||
interface Proxy {
|
||||
address: string;
|
||||
isOwned: boolean;
|
||||
type: ProxyType;
|
||||
}
|
||||
|
||||
interface ProxyState {
|
||||
hasOwned: boolean;
|
||||
proxies: Proxy[];
|
||||
}
|
||||
|
||||
function createProxy (address: string, { genesisHash, name, tags = [] }: CreateOptions, success: string): ActionStatus {
|
||||
// we will fill in all the details below
|
||||
const status = { action: 'create' } as ActionStatus;
|
||||
@ -55,28 +44,10 @@ function createProxy (address: string, { genesisHash, name, tags = [] }: CreateO
|
||||
|
||||
function ProxyAdd ({ className = '', onClose, onStatusChange }: Props): React.ReactElement<Props> {
|
||||
const { api, isDevelopment } = useApi();
|
||||
const { allAccounts } = useAccounts();
|
||||
const { t } = useTranslation();
|
||||
const [{ isNameValid, name }, setName] = useState({ isNameValid: false, name: '' });
|
||||
const [stashAddress, setStashAddress] = useState<string | null>(null);
|
||||
const [{ hasOwned }, setProxies] = useState<ProxyState>({ hasOwned: false, proxies: [] });
|
||||
|
||||
useEffect((): void => {
|
||||
if (stashAddress) {
|
||||
api.query.proxy
|
||||
.proxies(stashAddress)
|
||||
.then(([_proxies]): void => {
|
||||
const proxies = _proxies.map(([accountId, type]): Proxy => ({
|
||||
address: accountId.toString(),
|
||||
isOwned: allAccounts.includes(accountId.toString()),
|
||||
type
|
||||
}));
|
||||
|
||||
setProxies({ hasOwned: proxies.some(({ isOwned }) => isOwned), proxies });
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
}, [allAccounts, api, stashAddress]);
|
||||
const { hasOwned } = useProxies(stashAddress);
|
||||
|
||||
const _createProxied = useCallback(
|
||||
(): void => {
|
||||
@ -96,14 +67,6 @@ function ProxyAdd ({ className = '', onClose, onStatusChange }: Props): React.Re
|
||||
[]
|
||||
);
|
||||
|
||||
const _onChangeStash = useCallback(
|
||||
(address: string | null): void => {
|
||||
setProxies({ hasOwned: false, proxies: [] });
|
||||
setStashAddress(address);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const isValid = isNameValid && !!stashAddress && hasOwned;
|
||||
|
||||
return (
|
||||
@ -120,7 +83,7 @@ function ProxyAdd ({ className = '', onClose, onStatusChange }: Props): React.Re
|
||||
help={t<string>('The address that you have a valid proxy setup for.')}
|
||||
isError={!hasOwned}
|
||||
label={t<string>('proxied account')}
|
||||
onChange={_onChangeStash}
|
||||
onChange={setStashAddress}
|
||||
placeholder={t<string>('stash address')}
|
||||
/>
|
||||
</Modal.Column>
|
||||
|
||||
58
packages/page-accounts/src/Accounts/useProxies.ts
Normal file
58
packages/page-accounts/src/Accounts/useProxies.ts
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright 2017-2020 @polkadot/app-accounts 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 { ProxyType } from '@polkadot/types/interfaces';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useAccounts, useApi, useIsMountedRef } from '@polkadot/react-hooks';
|
||||
|
||||
interface Proxy {
|
||||
address: string;
|
||||
isOwned: boolean;
|
||||
type: ProxyType;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasOwned: boolean;
|
||||
owned: Proxy[];
|
||||
proxies: Proxy[];
|
||||
}
|
||||
|
||||
const EMPTY_STATE: State = {
|
||||
hasOwned: false,
|
||||
owned: [],
|
||||
proxies: []
|
||||
};
|
||||
|
||||
export default function useProxies (address?: string | null): State {
|
||||
const { api } = useApi();
|
||||
const { allAccounts } = useAccounts();
|
||||
const mountedRef = useIsMountedRef();
|
||||
const [known, setState] = useState<State>(EMPTY_STATE);
|
||||
|
||||
useEffect((): void => {
|
||||
setState(EMPTY_STATE);
|
||||
|
||||
address &&
|
||||
api.query.proxy
|
||||
.proxies(address)
|
||||
.then(([_proxies]): void => {
|
||||
const proxies = _proxies.map(([accountId, type]): Proxy => ({
|
||||
address: accountId.toString(),
|
||||
isOwned: allAccounts.includes(accountId.toString()),
|
||||
type
|
||||
}));
|
||||
const owned = proxies.filter(({ isOwned }) => isOwned);
|
||||
|
||||
mountedRef.current && setState({
|
||||
hasOwned: owned.length !== 0,
|
||||
owned,
|
||||
proxies
|
||||
});
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [allAccounts, api, address, mountedRef]);
|
||||
|
||||
return known;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user