feat: add export functionality for multisig signatories as JSON (#11408)

This commit is contained in:
Arjun Porwal 2025-03-25 09:16:44 +05:30 committed by GitHub
parent 3798e115f1
commit 9ec6206ff5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 3 deletions

View File

@ -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<RecoveryConfig>) => opt.unwrapOr(null)
};
function Account ({ account: { address, meta }, className = '', delegation, filter, isFavorite, proxy, setBalance, toggleFavorite }: Props): React.ReactElement<Props> | null {
function Account ({ account: { address, meta }, className = '', delegation, filter, isFavorite, onStatusChange, proxy, setBalance, toggleFavorite }: Props): React.ReactElement<Props> | 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 && (
<Menu.Item
icon='database'
key='backupJson'
label={t('Export JSON file with signatories')}
onClick={_onExportMultisig}
/>
),
!(isExternal || isHardware || isInjected || isMultisig || isDevelopment) && (
<Menu.Item
icon='edit'
@ -466,7 +502,7 @@ function Account ({ account: { address, meta }, className = '', delegation, filt
/>
])
].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;

View File

@ -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(