diff --git a/packages/page-accounts/src/Accounts/Account.tsx b/packages/page-accounts/src/Accounts/Account.tsx index f8ea5f5e96d6..7e8b6dddccc8 100644 --- a/packages/page-accounts/src/Accounts/Account.tsx +++ b/packages/page-accounts/src/Accounts/Account.tsx @@ -15,6 +15,7 @@ import type { ProxyDefinition, RecoveryConfig } from '@polkadot/types/interfaces import type { KeyringAddress, KeyringJson$Meta } from '@polkadot/ui-keyring/types'; import type { AccountBalance, Delegation } from '../types.js'; +import FileSaver from 'file-saver'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import useAccountLocks from '@polkadot/app-referenda/useAccountLocks'; @@ -49,6 +50,7 @@ interface Props { proxy?: [ProxyDefinition[], BN]; setBalance: (address: string, value: AccountBalance) => void; toggleFavorite: (address: string) => void; + onStatusChange: (status: ActionStatus) => void; } interface DemocracyUnlockable { @@ -157,7 +159,7 @@ const transformRecovery = { transform: (opt: Option) => opt.unwrapOr(null) }; -function Account ({ account: { address, meta }, className = '', delegation, filter, isFavorite, proxy, setBalance, toggleFavorite }: Props): React.ReactElement | null { +function Account ({ account: { address, meta }, className = '', delegation, filter, isFavorite, onStatusChange, proxy, setBalance, toggleFavorite }: Props): React.ReactElement | null { const { t } = useTranslation(); const [isExpanded, toggleIsExpanded] = useToggle(false); const { queueExtrinsic } = useQueue(); @@ -275,6 +277,32 @@ function Account ({ account: { address, meta }, className = '', delegation, filt [address, t] ); + const _onExportMultisig = useCallback(() => { + try { + if (!isMultisig) { + throw new Error('not a multisig account'); + } + + if (!meta.who) { + throw new Error('signatories not found'); + } + + const signatories: string[] = meta.who; + const blob = new Blob([JSON.stringify(signatories, null, 2)], { type: 'application/json; charset=utf-8' }); + + FileSaver.saveAs(blob, `${accName}_${address}_${new Date().getTime()}.json`); + } catch (error) { + const status: ActionStatus = { + account: address, + action: 'export', + message: (error as Error).message, + status: 'error' + }; + + onStatusChange(status); + } + }, [accName, address, isMultisig, meta.who, onStatusChange]); + const _clearDemocracyLocks = useCallback( () => democracyUnlockTx && queueExtrinsic({ accountId: address, @@ -380,6 +408,14 @@ function Account ({ account: { address, meta }, className = '', delegation, filt onClick={toggleBackup} /> ), + !(isInjected || isDevelopment) && isMultisig && ( + + ), !(isExternal || isHardware || isInjected || isMultisig || isDevelopment) && ( ]) ].filter((i) => i), - [_clearDemocracyLocks, _clearReferendaLocks, _showOnHardware, _vestingVest, api, apiIdentity.tx.identity, enableIdentity, delegation, democracyUnlockTx, genesisHash, identity, isDevelopment, isDevelopmentApiProps, isEthereumApiProps, isEditable, isEthereum, isExternal, isHardware, isInjected, isMultisig, multiInfos, onSetGenesisHash, proxy, referendaUnlockTx, recoveryInfo, t, toggleBackup, toggleDelegate, toggleDerive, toggleForget, toggleIdentityMain, toggleIdentitySub, toggleMultisig, togglePassword, toggleProxyOverview, toggleRecoverAccount, toggleRecoverSetup, toggleUndelegate, vestingVestTx]); + [_clearDemocracyLocks, _clearReferendaLocks, _showOnHardware, _vestingVest, _onExportMultisig, api, apiIdentity.tx.identity, enableIdentity, delegation, democracyUnlockTx, genesisHash, identity, isDevelopment, isDevelopmentApiProps, isEthereumApiProps, isEditable, isEthereum, isExternal, isHardware, isInjected, isMultisig, multiInfos, onSetGenesisHash, proxy, referendaUnlockTx, recoveryInfo, t, toggleBackup, toggleDelegate, toggleDerive, toggleForget, toggleIdentityMain, toggleIdentitySub, toggleMultisig, togglePassword, toggleProxyOverview, toggleRecoverAccount, toggleRecoverSetup, toggleUndelegate, vestingVestTx]); if (!isVisible) { return null; diff --git a/packages/page-accounts/src/Accounts/index.tsx b/packages/page-accounts/src/Accounts/index.tsx index e0765bc651d6..530e5a96ec8e 100644 --- a/packages/page-accounts/src/Accounts/index.tsx +++ b/packages/page-accounts/src/Accounts/index.tsx @@ -235,6 +235,7 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen filter={filterOn} isFavorite={isFavorite} key={address} + onStatusChange={onStatusChange} proxy={proxies?.[index]} setBalance={setBalance} toggleFavorite={toggleFavorite} @@ -243,7 +244,7 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen return all; }, {}), - [accountsMap, filterOn, proxies, setBalance, toggleFavorite] + [accountsMap, filterOn, proxies, setBalance, toggleFavorite, onStatusChange] ); const groups = useMemo(