Support for time-delay proxy params (defaults) (#3358)

* Support for time-delay proxy params (defaults)

* All proxy queries adjusted

* Proxy extraction

* Re-use proxy map

* Update after testing

* Cleanups

* Typ detection based on args

* CHANGELOG
This commit is contained in:
Jaco Greeff 2020-08-10 19:07:12 +02:00 committed by GitHub
parent 5ccfc5beb8
commit 0ed89585fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 32 deletions

View File

@ -1,5 +1,9 @@
# CHANGELOG
## 0.54.0-beta.x
- Base support for time-delay proxies (API-level only, both old and new calls)
## 0.53.1 Aug 10, 2020
- ko i18n first-round support (Thanks to https://github.com/hskang9)

View File

@ -5,7 +5,7 @@
import { SubmittableExtrinsic } from '@polkadot/api/types';
import { DeriveBalancesAll, DeriveDemocracyLock } from '@polkadot/api-derive/types';
import { ActionStatus } from '@polkadot/react-components/Status/types';
import { AccountId, ProxyType, RecoveryConfig } from '@polkadot/types/interfaces';
import { ProxyDefinition, RecoveryConfig } from '@polkadot/types/interfaces';
import { KeyringAddress } from '@polkadot/ui-keyring/types';
import { Delegation } from '../types';
@ -43,7 +43,7 @@ interface Props {
delegation?: Delegation;
filter: string;
isFavorite: boolean;
proxy?: [[AccountId, ProxyType][], BN];
proxy?: [ProxyDefinition[], BN];
setBalance: (address: string, value: BN) => void;
toggleFavorite: (address: string) => void;
}

View File

@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ActionStatus } from '@polkadot/react-components/Status/types';
import { AccountId, ProxyType, Voting } from '@polkadot/types/interfaces';
import { AccountId, ProxyDefinition, ProxyType, Voting } from '@polkadot/types/interfaces';
import { Delegation, SortedAccount } from '../types';
import BN from 'bn.js';
@ -74,7 +74,14 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen
const [sortedAccountsWithDelegation, setSortedAccountsWithDelegation] = useState<SortedAccount[] | undefined>();
const [{ sortedAccounts, sortedAddresses }, setSorted] = useState<Sorted>({ sortedAccounts: [], sortedAddresses: [] });
const delegations = useCall<Voting[]>(api.query.democracy?.votingOf?.multi, [sortedAddresses]);
const proxies = useCall<[[AccountId, ProxyType][], BN][]>(api.query.proxy?.proxies.multi, [sortedAddresses]);
const proxies = useCall<[ProxyDefinition[], BN][]>(api.query.proxy?.proxies.multi, [sortedAddresses], {
transform: (result: [([AccountId, ProxyType] | ProxyDefinition)[], BN][]): [ProxyDefinition[], BN][] =>
api.tx.proxy.addProxy.meta.args.length === 4
? result as [ProxyDefinition[], BN][]
: (result as [[AccountId, ProxyType][], BN][]).map(([arr, bn]): [ProxyDefinition[], BN] =>
[arr.map(([delegate, proxyType]): ProxyDefinition => api.createType('ProxyDefinition', { delegate, proxyType })), bn]
)
});
const isLoading = useLoadingDelay();
useEffect((): void => {

View File

@ -4,7 +4,7 @@
import { ApiPromise } from '@polkadot/api';
import { SubmittableExtrinsic } from '@polkadot/api/types';
import { AccountId, ProxyType } from '@polkadot/types/interfaces';
import { AccountId, ProxyDefinition, ProxyType } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
@ -20,7 +20,7 @@ type PrevProxy = [AccountId, ProxyType];
interface Props {
className?: string;
onClose: () => void;
previousProxy?: [PrevProxy[], BN];
previousProxy?: [ProxyDefinition[], BN];
proxiedAccount: string;
}
@ -50,6 +50,22 @@ function createExtrinsic (api: ApiPromise, batchPrevious: SubmittableExtrinsic<'
return api.tx.utility.batch([...batchPrevious, ...batchAdded]);
}
function createAddProxy (api: ApiPromise, account: AccountId, type: ProxyType): SubmittableExtrinsic<'promise'> {
return api.tx.proxy.addProxy.meta.args.length === 2
? api.tx.proxy.addProxy(account, type)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore new version
: api.tx.proxy.addProxy(account, type, 0);
}
function createRmProxy (api: ApiPromise, account: AccountId, type: ProxyType): SubmittableExtrinsic<'promise'> {
return api.tx.proxy.removeProxy.meta.args.length === 2
? api.tx.proxy.removeProxy(account, type)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore new version
: api.tx.proxy.removeProxy(account, type, 0);
}
function PrevProxy ({ index, onRemove, typeOpts, value: [accountId, type] }: PrevProxyProps): React.ReactElement<PrevProxyProps> {
const { t } = useTranslation();
@ -135,22 +151,17 @@ function NewProxy ({ index, onChangeAccount, onChangeType, onRemove, typeOpts, v
function ProxyOverview ({ className, onClose, previousProxy, proxiedAccount }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
// the stack of extrinsics on the previous proxies
const [batchStackPrevious, setBatchStackPrevious] = useState<SubmittableExtrinsic<'promise'>[]>([]);
// the stack of extrinsics on newly added proxies
const [batchStackAdded, setBatchStackAdded] = useState<SubmittableExtrinsic<'promise'>[]>([]);
// the final extrinsic (either single or a batch)
const [extrinsic, setExtrinsic] = useState<SubmittableExtrinsic<'promise'> | null>(null);
// list of previous accounts and proxy types
const [previousProxyAccountsTypes] = previousProxy || [];
// actualized list of previous proxy including new changes (deletion if any)
const [previousProxyDisplay, setPreviousProxyDisplay] = useState<[AccountId, ProxyType][] | undefined>(previousProxyAccountsTypes);
// actualized list of new proxies (additions, if any)
const [addedProxies, setAddedProxies] = useState<[AccountId, ProxyType][]>([]);
const [previousProxyDisplay, setPreviousProxyDisplay] = useState<PrevProxy[] | undefined>(
previousProxy?.[0].map(({ delegate, proxyType }): [AccountId, ProxyType] => [delegate, proxyType]) || undefined
);
const [addedProxies, setAddedProxies] = useState<PrevProxy[]>([]);
useEffect(() => {
if (batchStackPrevious.length || batchStackAdded.length) {
setExtrinsic(createExtrinsic(api, batchStackPrevious, batchStackAdded));
setExtrinsic(() => createExtrinsic(api, batchStackPrevious, batchStackAdded));
}
}, [api, batchStackPrevious, batchStackAdded]);
@ -172,7 +183,7 @@ function ProxyOverview ({ className, onClose, previousProxy, proxiedAccount }: P
: [...prevState, newProxy];
});
setBatchStackAdded((prev) => prev.concat(api.tx.proxy.addProxy(newAccount, newType)));
setBatchStackAdded((prev) => prev.concat(createAddProxy(api, newAccount, newType)));
},
[api, proxiedAccount]
);
@ -188,7 +199,7 @@ function ProxyOverview ({ className, onClose, previousProxy, proxiedAccount }: P
const _delPrev = useCallback(
(accountId: AccountId, type: ProxyType, index: number) => {
setPreviousProxyDisplay((previousProxyDisplay) => previousProxyDisplay?.filter((_, i) => i !== index));
setBatchStackPrevious((batchStackPrevious) => [...batchStackPrevious, api.tx.proxy.removeProxy(accountId, type)]);
setBatchStackPrevious((batchStackPrevious) => [...batchStackPrevious, createRmProxy(api, accountId, type)]);
},
[api]
);
@ -211,7 +222,7 @@ function ProxyOverview ({ className, onClose, previousProxy, proxiedAccount }: P
setBatchStackAdded((batchStackAdded): SubmittableExtrinsic<'promise'>[] => {
const newBatchAdded = batchStackAdded.filter((_, i) => i !== index);
newBatchAdded.push(api.tx.proxy.addProxy(accountId, oldType));
newBatchAdded.push(createAddProxy(api, accountId, oldType));
return newBatchAdded;
});
@ -238,7 +249,7 @@ function ProxyOverview ({ className, onClose, previousProxy, proxiedAccount }: P
const newBatchStackAdded = batchStackAdded.filter((_, i) => i !== index);
// Then add the new extrinsic to the batch stack with the new account
newBatchStackAdded.push(api.tx.proxy.addProxy(oldAccount, newType));
newBatchStackAdded.push(createAddProxy(api, oldAccount, newType));
setBatchStackAdded(newBatchStackAdded);
},
[addedProxies, api, batchStackAdded]
@ -269,7 +280,7 @@ function ProxyOverview ({ className, onClose, previousProxy, proxiedAccount }: P
{previousProxyDisplay?.map((value, index) => (
<PrevProxy
index={index}
key={`${value[0].toString()}-${index}`}
key={`${value.toString()}-${index}`}
onRemove={_delPrev}
typeOpts={typeOpts}
value={value}
@ -278,7 +289,7 @@ function ProxyOverview ({ className, onClose, previousProxy, proxiedAccount }: P
{addedProxies.map((value, index) => (
<NewProxy
index={index}
key={`${value[0].toString()}-${index}`}
key={`${value.toString()}-${index}`}
onChangeAccount={_changeProxyAccount}
onChangeType={_changeProxyType}
onRemove={_delProxy}

View File

@ -2,13 +2,18 @@
// 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 { AccountId, BalanceOf, ProxyDefinition, ProxyType } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import BN from 'bn.js';
import { useEffect, useState } from 'react';
import { useAccounts, useApi, useIsMountedRef } from '@polkadot/react-hooks';
import { Vec } from '@polkadot/types';
import { BN_ZERO } from '@polkadot/util';
interface Proxy {
address: string;
delay: BN;
isOwned: boolean;
type: ProxyType;
}
@ -25,6 +30,17 @@ const EMPTY_STATE: State = {
proxies: []
};
function createProxy (allAccounts: string[], delegate: AccountId, type: ProxyType, delay = BN_ZERO): Proxy {
const address = delegate.toString();
return {
address,
delay,
isOwned: allAccounts.includes(address),
type
};
}
export default function useProxies (address?: string | null): State {
const { api } = useApi();
const { allAccounts } = useAccounts();
@ -36,13 +52,15 @@ export default function useProxies (address?: string | null): State {
address && api.query.proxy &&
api.query.proxy
.proxies(address)
.proxies<ITuple<[Vec<ITuple<[AccountId, ProxyType]> | ProxyDefinition>, BalanceOf]>>(address)
.then(([_proxies]): void => {
const proxies = _proxies.map(([accountId, type]): Proxy => ({
address: accountId.toString(),
isOwned: allAccounts.includes(accountId.toString()),
type
}));
const proxies = api.tx.proxy.addProxy.meta.args.length === 4
? (_proxies as ProxyDefinition[]).map(({ delay, delegate, proxyType }) =>
createProxy(allAccounts, delegate, proxyType, delay)
)
: (_proxies as [AccountId, ProxyType][]).map(([delegate, proxyType]) =>
createProxy(allAccounts, delegate, proxyType)
);
const owned = proxies.filter(({ isOwned }) => isOwned);
mountedRef.current && setState({

View File

@ -4,7 +4,8 @@
import { SubmittableExtrinsic } from '@polkadot/api/types';
import { QueueTx } from '@polkadot/react-components/Status/types';
import { Call, Multisig, ProxyType } from '@polkadot/types/interfaces';
import { AccountId, BalanceOf, Call, Multisig, ProxyDefinition, ProxyType } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { AddressProxy } from './types';
import React, { useEffect, useState } from 'react';
@ -121,8 +122,10 @@ async function queryForMultisig (api: ApiPromise, requestAddress: string, proxyA
async function queryForProxy (api: ApiPromise, allAccounts: string[], address: string, tx: SubmittableExtrinsic<'promise'>): Promise<ProxyState | null> {
if (isFunction(api.query.proxy?.proxies)) {
const { isProxied } = extractExternal(address);
const [_proxies] = await api.query.proxy.proxies(address);
const proxies = _proxies.map(([accountId, type]): [string, ProxyType] => [accountId.toString(), type]);
const [_proxies] = await api.query.proxy.proxies<ITuple<[Vec<ITuple<[AccountId, ProxyType]> | ProxyDefinition>, BalanceOf]>>(address);
const proxies = api.tx.proxy.addProxy.meta.args.length === 4
? (_proxies as ProxyDefinition[]).map(({ delegate, proxyType }): [string, ProxyType] => [delegate.toString(), proxyType])
: (_proxies as [AccountId, ProxyType][]).map(([delegate, proxyType]): [string, ProxyType] => [delegate.toString(), proxyType]);
const proxiesFilter = filterProxies(allAccounts, tx, proxies);
if (proxiesFilter.length) {