From 0ed89585fc8a7e2b0c980ebc353f9a0cea39b419 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 10 Aug 2020 19:07:12 +0200 Subject: [PATCH] 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 --- CHANGELOG.md | 4 ++ .../page-accounts/src/Accounts/Account.tsx | 4 +- packages/page-accounts/src/Accounts/index.tsx | 11 ++++- .../src/Accounts/modals/ProxyOverview.tsx | 47 ++++++++++++------- .../page-accounts/src/Accounts/useProxies.ts | 32 ++++++++++--- packages/react-signer/src/Address.tsx | 9 ++-- 6 files changed, 75 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f437942e65..08fb632b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/packages/page-accounts/src/Accounts/Account.tsx b/packages/page-accounts/src/Accounts/Account.tsx index 2485da5a86..d995b5f2d0 100644 --- a/packages/page-accounts/src/Accounts/Account.tsx +++ b/packages/page-accounts/src/Accounts/Account.tsx @@ -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; } diff --git a/packages/page-accounts/src/Accounts/index.tsx b/packages/page-accounts/src/Accounts/index.tsx index f5979abd91..dd6bab5dd2 100644 --- a/packages/page-accounts/src/Accounts/index.tsx +++ b/packages/page-accounts/src/Accounts/index.tsx @@ -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(); const [{ sortedAccounts, sortedAddresses }, setSorted] = useState({ sortedAccounts: [], sortedAddresses: [] }); const delegations = useCall(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 => { diff --git a/packages/page-accounts/src/Accounts/modals/ProxyOverview.tsx b/packages/page-accounts/src/Accounts/modals/ProxyOverview.tsx index f5619fbdc3..c0311e2088 100644 --- a/packages/page-accounts/src/Accounts/modals/ProxyOverview.tsx +++ b/packages/page-accounts/src/Accounts/modals/ProxyOverview.tsx @@ -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 { const { t } = useTranslation(); @@ -135,22 +151,17 @@ function NewProxy ({ index, onChangeAccount, onChangeType, onRemove, typeOpts, v function ProxyOverview ({ className, onClose, previousProxy, proxiedAccount }: Props): React.ReactElement { const { t } = useTranslation(); const { api } = useApi(); - // the stack of extrinsics on the previous proxies const [batchStackPrevious, setBatchStackPrevious] = useState[]>([]); - // the stack of extrinsics on newly added proxies const [batchStackAdded, setBatchStackAdded] = useState[]>([]); - // the final extrinsic (either single or a batch) const [extrinsic, setExtrinsic] = useState | 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( + previousProxy?.[0].map(({ delegate, proxyType }): [AccountId, ProxyType] => [delegate, proxyType]) || undefined + ); + const [addedProxies, setAddedProxies] = useState([]); 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) => ( ( | 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({ diff --git a/packages/react-signer/src/Address.tsx b/packages/react-signer/src/Address.tsx index 9b8fb52f4e..56b53ee5a0 100644 --- a/packages/react-signer/src/Address.tsx +++ b/packages/react-signer/src/Address.tsx @@ -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 { 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 | 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) {