diff --git a/src/components/Entries.tsx b/src/components/Entries.tsx index a11d192..c76cad2 100644 --- a/src/components/Entries.tsx +++ b/src/components/Entries.tsx @@ -1,6 +1,6 @@ import BaseIdentityIcon from '@polkadot/react-identicon'; import { KeyringAddress, KeyringJson } from '@polkadot/ui-keyring/types'; -import { Button, Collapse, Empty, Progress, Space, Table, Typography } from 'antd'; +import { Button, Collapse, Empty, Progress, Space, Spin, Table, Typography } from 'antd'; import { ColumnsType } from 'antd/lib/table'; import { intersection, isEmpty } from 'lodash'; import { useCallback, useRef, useState } from 'react'; @@ -258,10 +258,12 @@ export function Entries({ return !(isConfirmed || isCancelled) ? ( <> - {!isEmpty(data) - ? // ? `${data.substring(0, CALL_DATA_LENGTH)}${data.length > CALL_DATA_LENGTH ? '...' : ''}` - toShortString(data, CALL_DATA_LENGTH) - : '-'} + {!isEmpty(data) ? ( + // ? `${data.substring(0, CALL_DATA_LENGTH)}${data.length > CALL_DATA_LENGTH ? '...' : ''}` + toShortString(data, CALL_DATA_LENGTH) + ) : ( + + )} ) : ( diff --git a/src/components/ExtrinsicLaunch.tsx b/src/components/ExtrinsicLaunch.tsx index cc60682..967de59 100644 --- a/src/components/ExtrinsicLaunch.tsx +++ b/src/components/ExtrinsicLaunch.tsx @@ -25,9 +25,10 @@ interface Props { className?: string; onTxSuccess?: (res: SubmittableResult) => void; onTxFail?: (res: SubmittableResult | null) => void; + onTxUpdate?: (res: SubmittableResult) => void; } -export function ExtrinsicLaunch({ className, onTxSuccess }: Props): React.ReactElement { +export function ExtrinsicLaunch({ className, onTxSuccess, onTxUpdate }: Props): React.ReactElement { const { t } = useTranslation(); const { api } = useApi(); const [accountId, setAccountId] = useState(null); @@ -181,6 +182,7 @@ export function ExtrinsicLaunch({ className, onTxSuccess }: Props): React.ReactE icon="sign-in-alt" label={t('Submit Transaction')} onSuccess={onTxSuccess} + onUpdate={onTxUpdate} isBusy={isBusy} multiRoot={multisigAccount?.address} /> diff --git a/src/components/ExtrinsicRecords.tsx b/src/components/ExtrinsicRecords.tsx index 17fd651..303dfba 100644 --- a/src/components/ExtrinsicRecords.tsx +++ b/src/components/ExtrinsicRecords.tsx @@ -230,22 +230,23 @@ export function ExtrinsicRecords() { setFirst(false); if (inProgress.length === 0 && confirmedAccount > 0) { setTabKey('confirmed'); + fetchConfirmed(); } } - }, [loadingInProgress, confirmedAccount, first, inProgress]); + }, [loadingInProgress, confirmedAccount, first, inProgress, fetchConfirmed]); + // Re-fetch list when page changes, only if already on that tab useEffect(() => { - fetchConfirmed(); - fetchCancelled(); - }, [networkConfig, fetchCancelled, fetchConfirmed]); - - useEffect(() => { - fetchConfirmed(); - }, [confirmedPage, fetchConfirmed, networkConfig]); + if (tabKey === 'confirmed') { + fetchConfirmed(); + } + }, [confirmedPage]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { - fetchCancelled(); - }, [cancelledPage, fetchCancelled, networkConfig]); + if (tabKey === 'cancelled') { + fetchCancelled(); + } + }, [cancelledPage]); // eslint-disable-line react-hooks/exhaustive-deps // eslint-disable-next-line complexity const handleChangeTab = (key: string) => { diff --git a/src/components/WalletState.tsx b/src/components/WalletState.tsx index 2924eda..73b82a7 100644 --- a/src/components/WalletState.tsx +++ b/src/components/WalletState.tsx @@ -323,6 +323,12 @@ export function WalletState(props: WalletStateProps) { setIsExtrinsicDisplay(false); queryInProgress(); }} + onTxUpdate={(status) => { + if (status.isInBlock) { + setIsExtrinsicDisplay(false); + queryInProgress(); + } + }} /> diff --git a/src/hooks/combineQuery.ts b/src/hooks/combineQuery.ts index 07aeb83..a7e3333 100644 --- a/src/hooks/combineQuery.ts +++ b/src/hooks/combineQuery.ts @@ -15,7 +15,7 @@ import { } from './subscan'; export interface MultisigAccountDetailResult { - multisigAccount: { id: string; threshold: number; members: string[] }; + multisigAccount: { id: string; threshold: number; members: string[] } | null; } export interface MultisigRecordCountResult { @@ -26,31 +26,43 @@ export function useMultisigAccountDetail(network: NetConfigV2 | undefined) { const subquery = useSubqueryMultisigAccountDetail(network); const subscan = useSubscanMultisigAccountDetail(network); - const fetcher = network?.api?.subscan ? subscan : subquery; + const useSubscan = !!network?.api?.subscan; + const fetchFn = useSubscan ? subscan.fetchData : subquery.fetchData; + const data = useSubscan ? subscan.data : subquery.data; + const loading = useSubscan ? subscan.loading : subquery.loading; - const fetchData = useCallback((account: string) => { - if (!account) { - return; - } - fetcher.fetchData(account); - }, []); + const fetchData = useCallback( + (account: string) => { + if (!account) { + return; + } + fetchFn(account); + }, + [fetchFn] + ); - return { fetchData, data: fetcher.data, loading: fetcher.loading }; + return { fetchData, data, loading }; } export function useMultisigRecordCount(network: NetConfigV2 | undefined) { const subquery = usSubqueryMultisigRecordCount(network); const subscan = usSubscanMultisigRecordCount(network); - const fetcher = network?.api?.subscan ? subscan : subquery; + const useSubscan = !!network?.api?.subscan; + const fetchFn = useSubscan ? subscan.fetchData : subquery.fetchData; + const data = useSubscan ? subscan.data : subquery.data; + const loading = useSubscan ? subscan.loading : subquery.loading; - const fetchData = useCallback((account: string, status: string) => { - if (!account) { - return; - } - fetcher.fetchData(account, status); - }, []); - return { fetchData, data: fetcher.data, loading: fetcher.loading }; + const fetchData = useCallback( + (account: string, status: string) => { + if (!account) { + return; + } + fetchFn(account, status); + }, + [fetchFn] + ); + return { fetchData, data, loading }; } export function useMultisigRecords( @@ -70,16 +82,19 @@ export function useMultisigRecords( const subquery = useSubqueryMultisigRecords(network); const subscan = useSubscanMultisigRecords(network); - const fetcher = network?.api?.subscan ? subscan : subquery; + const useSubscan = !!network?.api?.subscan; + const fetchFn = useSubscan ? subscan.fetchData : subquery.fetchData; + const data = useSubscan ? subscan.data : subquery.data; + const loading = useSubscan ? subscan.loading : subquery.loading; // eslint-disable-next-line no-magic-numbers const fetchData = useCallback(() => { if (!account) { return; } - fetcher.fetchData(account, status, offset, limit); - }, [account, offset, status]); - return { fetchData, data: fetcher.data, loading: fetcher.loading }; + fetchFn(account, status, offset, limit); + }, [account, offset, status, limit, fetchFn]); + return { fetchData, data, loading }; } export function useDataSourceTools(network: NetConfigV2 | undefined) { diff --git a/src/hooks/multisig.ts b/src/hooks/multisig.ts index 731aa8e..5f07cb4 100644 --- a/src/hooks/multisig.ts +++ b/src/hooks/multisig.ts @@ -27,10 +27,6 @@ export function useMultisig(acc?: string) { }; const { fetchData: fetchInProgress, data: inProgressData } = useMultisigRecords(networkConfig, fetchInprogressParams); - useEffect(() => { - fetchInProgress(); - }, [networkConfig, fetchInProgress]); - const queryInProgress = useCallback( // eslint-disable-next-line complexity async (silent = false) => { diff --git a/src/hooks/subscan.ts b/src/hooks/subscan.ts index e075774..c4f14a5 100644 --- a/src/hooks/subscan.ts +++ b/src/hooks/subscan.ts @@ -21,167 +21,177 @@ function subscanRecordsStatusConverter(status: string) { export const useMultisigAccountDetail = (network: NetConfigV2 | undefined) => { const [userInfo, SetUserInfo] = useState(); const [loading, SetLoading] = useState(false); - const fetchData = useCallback(async (account: string) => { - if (!network || !account) return; + const fetchData = useCallback( + async (account: string) => { + if (!network || !account) return; - SetLoading(true); - try { - const { data } = await axiosRequest.post<{ - account: { - multisig: { - multi_account_member: { - address: string; - }[]; - threshold: number; + SetLoading(true); + try { + const { data } = await axiosRequest.post<{ + account: { + multisig: { + multi_account_member: { + address: string; + }[]; + threshold: number; + }; }; - }; - }>(`${network.api?.subscan}/api/v2/scan/search`, { - key: account, - }); - SetUserInfo({ - multisigAccount: { - id: account, - threshold: data.data.account.multisig.threshold, - members: data.data.account.multisig.multi_account_member.map((o) => o.address), - }, - }); - SetLoading(false); - } catch (error) { - SetLoading(false); - } - }, []); + }>(`${network.api?.subscan}/api/v2/scan/search`, { + key: account, + }); + SetUserInfo({ + multisigAccount: { + id: account, + threshold: data.data.account.multisig.threshold, + members: data.data.account.multisig.multi_account_member.map((o) => o.address), + }, + }); + SetLoading(false); + } catch (error) { + SetUserInfo({ multisigAccount: null }); + SetLoading(false); + } + }, + [network] + ); return { fetchData, data: userInfo, loading }; }; export const useMultisigRecordCount = (network: NetConfigV2 | undefined) => { const [userInfo, SetUserInfo] = useState(); const [loading, SetLoading] = useState(false); - const fetchData = useCallback(async (account: string, status: string) => { - if (!network || !account || !status) return; + const fetchData = useCallback( + async (account: string, status: string) => { + if (!network || !account || !status) return; - SetLoading(true); - try { - const { data } = await axiosRequest.post<{ - count: number; - multisig: { - multi_id: string; - call_hash: string; - status: string; - block_timestamp: number; - }[]; - }>(`${network.api?.subscan}/api/scan/multisigs/details`, { - account, - page: 0, - row: 1, - status: subscanRecordsStatusConverter(status), - }); - SetUserInfo({ - multisigRecords: { totalCount: data.data.count }, - }); - SetLoading(false); - } catch (error) { - SetLoading(false); - } - }, []); + SetLoading(true); + try { + const { data } = await axiosRequest.post<{ + count: number; + multisig: { + multi_id: string; + call_hash: string; + status: string; + block_timestamp: number; + }[]; + }>(`${network.api?.subscan}/api/scan/multisigs/details`, { + account, + page: 0, + row: 1, + status: subscanRecordsStatusConverter(status), + }); + SetUserInfo({ + multisigRecords: { totalCount: data.data.count }, + }); + SetLoading(false); + } catch (error) { + SetLoading(false); + } + }, + [network] + ); return { fetchData, data: userInfo, loading }; }; export const useMultisigRecords = (network: NetConfigV2 | undefined) => { const [userInfo, SetUserInfo] = useState(); const [loading, SetLoading] = useState(false); - const fetchData = useCallback(async (account: string, status: string, offset = 0, limit = 100) => { - if (!network || !account || !status) return; + const fetchData = useCallback( + async (account: string, status: string, offset = 0, limit = 100) => { + if (!network || !account || !status) return; - SetLoading(true); - try { - const { data } = await axiosRequest.post<{ - count: number; - multisig: { - multi_id: string; - multi_account_display: { address: string }; - call_hash: string; - call_data: string; - call_module: string; - call_module_function: string; - confirm_extrinsic_idx: string; - cancel_extrinsic_idx: string; - block_timestamp: number; - status: string; - approve_record: { - account_display: { address: string }; - extrinsic_index: string; - approve_type: string; - timestamp: number; - }[]; - cancel_record: { - account_display: { address: string }; - extrinsic_index: string; - approve_type: string; - timestamp: number; + SetLoading(true); + try { + const { data } = await axiosRequest.post<{ + count: number; + multisig: { + multi_id: string; + multi_account_display: { address: string }; + call_hash: string; + call_data: string; + call_module: string; + call_module_function: string; + confirm_extrinsic_idx: string; + cancel_extrinsic_idx: string; + block_timestamp: number; + status: string; + approve_record: { + account_display: { address: string }; + extrinsic_index: string; + approve_type: string; + timestamp: number; + }[]; + cancel_record: { + account_display: { address: string }; + extrinsic_index: string; + approve_type: string; + timestamp: number; + }[]; }[]; - }[]; - }>(`${network.api?.subscan}/api/scan/multisigs/details`, { - account, - page: offset, - row: limit, - status: subscanRecordsStatusConverter(status), - }); - SetUserInfo({ - multisigRecords: { - totalCount: data.data.count, - nodes: data.data.multisig?.map((item) => { - return { - multisigAccountId: account, - callHash: item.call_hash, - callData: item.call_data, - createExtrinsicIdx: item.multi_id, - confirmExtrinsicIdx: item.confirm_extrinsic_idx, - cancelExtrinsicIdx: item.cancel_extrinsic_idx, - timestamp: item.block_timestamp?.toString(), - approveRecords: { - nodes: - item.approve_record?.map((record) => { - return { - id: record.account_display.address + record.extrinsic_index, - account: record.account_display.address, - approveTimepoint: record.extrinsic_index, - approveTimestamp: record.timestamp.toString(), - approveType: record.approve_type, - }; - }) || [], - }, - cancelRecords: { - nodes: - item.cancel_record?.map((record) => { - return { - account: record.account_display.address, - cancelTimepoint: record.extrinsic_index, - cancelTimestamp: record.timestamp.toString(), - }; - }) || [], - }, - block: { - id: '', - extrinsics: { - nodes: [], + }>(`${network.api?.subscan}/api/scan/multisigs/details`, { + account, + page: offset, + row: limit, + status: subscanRecordsStatusConverter(status), + }); + SetUserInfo({ + multisigRecords: { + totalCount: data.data.count, + nodes: data.data.multisig?.map((item) => { + return { + multisigAccountId: account, + callHash: item.call_hash, + callData: item.call_data, + createExtrinsicIdx: item.multi_id, + confirmExtrinsicIdx: item.confirm_extrinsic_idx, + cancelExtrinsicIdx: item.cancel_extrinsic_idx, + timestamp: item.block_timestamp?.toString(), + approveRecords: { + nodes: + item.approve_record?.map((record) => { + return { + id: record.account_display.address + record.extrinsic_index, + account: record.account_display.address, + approveTimepoint: record.extrinsic_index, + approveTimestamp: record.timestamp.toString(), + approveType: record.approve_type, + }; + }) || [], }, - }, - confirmBlock: { - id: '', - extrinsics: { - nodes: [], + cancelRecords: { + nodes: + item.cancel_record?.map((record) => { + return { + account: record.account_display.address, + cancelTimepoint: record.extrinsic_index, + cancelTimestamp: record.timestamp.toString(), + }; + }) || [], }, - }, - }; - }), - }, - }); - SetLoading(false); - } catch (error) { - console.info('useMultisigRecords::error', error); - SetLoading(false); - } - }, []); + block: { + id: '', + extrinsics: { + nodes: [], + }, + }, + confirmBlock: { + id: '', + extrinsics: { + nodes: [], + }, + }, + }; + }), + }, + }); + SetLoading(false); + } catch (error) { + console.info('useMultisigRecords::error', error); + SetLoading(false); + } + }, + [network] + ); return { fetchData, data: userInfo, loading }; }; diff --git a/src/providers/multisig-provider.tsx b/src/providers/multisig-provider.tsx index 60427f0..9f9a769 100644 --- a/src/providers/multisig-provider.tsx +++ b/src/providers/multisig-provider.tsx @@ -37,8 +37,13 @@ export const EntriesProvider = ({ children }: React.PropsWithChildren) const [isPageLocked, setIsPageLock] = useState(false); const { networkConfig } = useApi(); const value = useMultisig(); + const { fetchInProgress } = value; const { account } = useParams<{ account: string }>(); + useEffect(() => { + fetchInProgress(); + }, [fetchInProgress]); + const { fetchData, data } = useMultisigRecordCount(networkConfig); const refreshConfirmedAccount = useCallback(() => {