From 746ffa980c1d3d4e88f77cac6b93c2633e8e3b60 Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Sat, 9 Dec 2023 16:35:52 +0000 Subject: [PATCH] fix: new recursive refresh txns mechanism and account info and txns are pooled together --- src/extension/apps/main/Root.tsx | 4 +- .../SendAssetModal/SendAssetModal.tsx | 18 +-- .../AssetFreezeTransactionContent.tsx | 13 +- .../SignTxnsModal/SignTxnsModalContent.tsx | 13 +- src/extension/constants/Limits.ts | 2 + src/extension/constants/index.ts | 1 + src/extension/enums/AccountsThunkEnum.ts | 1 + src/extension/features/accounts/slice.ts | 104 ++++++++----- .../thunks/fetchAccountsFromStorageThunk.ts | 21 ++- .../features/accounts/thunks/index.ts | 3 +- .../startPollingForAccountInformationThunk.ts | 9 +- .../thunks/updateAccountInformationThunk.ts | 99 ------------ .../thunks/updateAccountTransactionsThunk.ts | 84 ----------- .../accounts/thunks/updateAccountsThunk.ts | 141 ++++++++++++++++++ .../features/accounts/types/IAccountUpdate.ts | 12 ++ .../features/accounts/types/IAccountsState.ts | 7 +- .../types/IFetchAccountsFromStoragePayload.ts | 8 +- .../types/IUpdateAccountInformationPayload.ts | 11 -- .../IUpdateAccountTransactionsPayload.ts | 11 -- .../accounts/types/IUpdateAccountsPayload.ts | 17 +++ .../features/accounts/types/index.ts | 4 +- ...tchAlgorandAccountTransactionsWithDelay.ts | 6 + .../accounts/utils/getInitialState.ts | 3 +- .../features/accounts/utils/index.ts | 1 + .../accounts/utils/refreshTransactions.ts | 87 +++++++++++ .../utils/updateAccountInformation.ts | 45 +++--- .../utils/updateAccountTransactions.ts | 112 +++++++------- .../pages/AccountPage/AccountPage.tsx | 6 +- .../MainAddAccountRouter.tsx | 39 +++-- src/extension/selectors/index.ts | 2 - .../useSelectUpdatingAccountInformation.ts | 14 -- .../useSelectUpdatingAccountTransactions.ts | 14 -- 32 files changed, 503 insertions(+), 409 deletions(-) create mode 100644 src/extension/constants/Limits.ts delete mode 100644 src/extension/features/accounts/thunks/updateAccountInformationThunk.ts delete mode 100644 src/extension/features/accounts/thunks/updateAccountTransactionsThunk.ts create mode 100644 src/extension/features/accounts/thunks/updateAccountsThunk.ts create mode 100644 src/extension/features/accounts/types/IAccountUpdate.ts delete mode 100644 src/extension/features/accounts/types/IUpdateAccountInformationPayload.ts delete mode 100644 src/extension/features/accounts/types/IUpdateAccountTransactionsPayload.ts create mode 100644 src/extension/features/accounts/types/IUpdateAccountsPayload.ts create mode 100644 src/extension/features/accounts/utils/refreshTransactions.ts delete mode 100644 src/extension/selectors/useSelectUpdatingAccountInformation.ts delete mode 100644 src/extension/selectors/useSelectUpdatingAccountTransactions.ts diff --git a/src/extension/apps/main/Root.tsx b/src/extension/apps/main/Root.tsx index 9166e994..649bf235 100644 --- a/src/extension/apps/main/Root.tsx +++ b/src/extension/apps/main/Root.tsx @@ -97,8 +97,8 @@ const Root: FC = () => { if (accounts.length < 1) { dispatch( fetchAccountsFromStorageThunk({ - updateAccountInformation: true, - updateAccountTransactions: true, + updateInformation: true, + updateTransactions: true, }) ); } diff --git a/src/extension/components/SendAssetModal/SendAssetModal.tsx b/src/extension/components/SendAssetModal/SendAssetModal.tsx index 7a1fe032..c0f46a30 100644 --- a/src/extension/components/SendAssetModal/SendAssetModal.tsx +++ b/src/extension/components/SendAssetModal/SendAssetModal.tsx @@ -41,10 +41,7 @@ import { ErrorCodeEnum } from '@extension/enums'; import { BaseExtensionError } from '@extension/errors'; // features -import { - updateAccountInformationThunk, - updateAccountTransactionsThunk, -} from '@extension/features/accounts'; +import { updateAccountsThunk } from '@extension/features/accounts'; import { setAmount, setError, @@ -400,17 +397,12 @@ const SendAssetModal: FC = ({ onClose }: IProps) => { // refresh the account transactions if (fromAccount) { - // force update the account information as we spent fees - dispatch( - updateAccountInformationThunk({ - accountIds: [fromAccount.id], - forceUpdate: true, - }) - ); + // force update the account information as we spent fees and refresh all the new transactions dispatch( - updateAccountTransactionsThunk({ + updateAccountsThunk({ accountIds: [fromAccount.id], - refresh: true, + forceInformationUpdate: true, + refreshTransactions: true, }) ); } diff --git a/src/extension/components/SignTxnsModal/AssetFreezeTransactionContent.tsx b/src/extension/components/SignTxnsModal/AssetFreezeTransactionContent.tsx index e0e02eca..7a26bc93 100644 --- a/src/extension/components/SignTxnsModal/AssetFreezeTransactionContent.tsx +++ b/src/extension/components/SignTxnsModal/AssetFreezeTransactionContent.tsx @@ -164,6 +164,7 @@ const AssetFreezeTransactionContent: FC = ({ (async () => { let account: IAccount | null; let accountInformation: IAccountInformation; + let encodedGenesisHash: string; if (!freezeAddress) { return; @@ -186,11 +187,18 @@ const AssetFreezeTransactionContent: FC = ({ setFetchingFreezeAccountInformation(true); + encodedGenesisHash = convertGenesisHashToHex( + network.genesisHash + ).toUpperCase(); account = AccountService.initializeDefaultAccount({ publicKey: AccountService.convertAlgorandAddressToPublicKey(freezeAddress), }); - accountInformation = await updateAccountInformation(account, { + accountInformation = await updateAccountInformation({ + address: freezeAddress, + currentAccountInformation: + account.networkInformation[encodedGenesisHash] || + AccountService.initializeDefaultAccountInformation(), logger, network, }); @@ -199,8 +207,7 @@ const AssetFreezeTransactionContent: FC = ({ ...account, networkInformation: { ...account.networkInformation, - [convertGenesisHashToHex(network.genesisHash).toUpperCase()]: - accountInformation, + [encodedGenesisHash]: accountInformation, }, }); setFetchingFreezeAccountInformation(false); diff --git a/src/extension/components/SignTxnsModal/SignTxnsModalContent.tsx b/src/extension/components/SignTxnsModal/SignTxnsModalContent.tsx index 2d07aea2..1467f55c 100644 --- a/src/extension/components/SignTxnsModal/SignTxnsModalContent.tsx +++ b/src/extension/components/SignTxnsModal/SignTxnsModalContent.tsx @@ -116,6 +116,7 @@ const SignTxnsModalContent: FC = ({ value.publicKey.toUpperCase() === encodedPublicKey.toUpperCase() ) || null; let accountInformation: IAccountInformation; + let encodedGenesisHash: string; // if we have this account, just return it if (account) { @@ -125,7 +126,17 @@ const SignTxnsModalContent: FC = ({ account = AccountService.initializeDefaultAccount({ publicKey: encodedPublicKey, }); - accountInformation = await updateAccountInformation(account, { + encodedGenesisHash = convertGenesisHashToHex( + network.genesisHash + ).toUpperCase(); + accountInformation = await updateAccountInformation({ + address: + AccountService.convertPublicKeyToAlgorandAddress( + encodedPublicKey + ), + currentAccountInformation: + account.networkInformation[encodedGenesisHash] || + AccountService.initializeDefaultAccountInformation(), delay: index * NODE_REQUEST_DELAY, logger, network, diff --git a/src/extension/constants/Limits.ts b/src/extension/constants/Limits.ts new file mode 100644 index 00000000..5c340d03 --- /dev/null +++ b/src/extension/constants/Limits.ts @@ -0,0 +1,2 @@ +export const DEFAULT_TRANSACTION_INDEXER_LIMIT: number = 20; +export const UPPER_TRANSACTION_INDEXER_LIMIT: number = 100; diff --git a/src/extension/constants/index.ts b/src/extension/constants/index.ts index aae996d4..703fb6d8 100644 --- a/src/extension/constants/index.ts +++ b/src/extension/constants/index.ts @@ -2,6 +2,7 @@ export * from './Dimensions'; export * from './Durations'; export * from './Keys'; export * from './Links'; +export * from './Limits'; export * from './Routes'; export * from './Urls'; export * from './Validation'; diff --git a/src/extension/enums/AccountsThunkEnum.ts b/src/extension/enums/AccountsThunkEnum.ts index 56e09abc..280a0c26 100644 --- a/src/extension/enums/AccountsThunkEnum.ts +++ b/src/extension/enums/AccountsThunkEnum.ts @@ -5,6 +5,7 @@ enum AccountsThunkEnum { StartPollingForAccountInformation = 'accounts/startPollingForAccountInformation', StopPollingForAccountInformation = 'accounts/stopPollingForAccountInformation', UpdateAccountInformation = 'accounts/updateAccountInformation', + UpdateAccounts = 'accounts/updateAccounts', UpdateAccountTransactions = 'accounts/updateAccountTransactions', } diff --git a/src/extension/features/accounts/slice.ts b/src/extension/features/accounts/slice.ts index 0b06f757..2feaa381 100644 --- a/src/extension/features/accounts/slice.ts +++ b/src/extension/features/accounts/slice.ts @@ -10,17 +10,25 @@ import { saveNewAccountThunk, startPollingForAccountInformationThunk, stopPollingForAccountInformationThunk, - updateAccountInformationThunk, - updateAccountTransactionsThunk, + updateAccountsThunk, } from './thunks'; // types -import { IAccount } from '@extension/types'; -import { IAccountsState } from './types'; +import { + IAccount, + IPendingActionMeta, + IRejectedActionMeta, +} from '@extension/types'; +import { + IAccountsState, + IAccountUpdate, + IUpdateAccountsPayload, +} from './types'; // utils import { upsertItemsById } from '@extension/utils'; import { getInitialState } from './utils'; +import { stat } from 'copy-webpack-plugin/types/utils'; const slice = createSlice({ extraReducers: (builder) => { @@ -96,50 +104,76 @@ const slice = createSlice({ state.pollingId = null; } ); - /** update account information **/ + /** update accounts **/ builder.addCase( - updateAccountInformationThunk.fulfilled, + updateAccountsThunk.fulfilled, (state: IAccountsState, action: PayloadAction) => { state.items = state.items.map( (account) => action.payload.find((value) => value.id === account.id) || account ); - state.updatingInformation = false; - } - ); - builder.addCase( - updateAccountInformationThunk.pending, - (state: IAccountsState) => { - state.updatingInformation = true; - } - ); - builder.addCase( - updateAccountInformationThunk.rejected, - (state: IAccountsState) => { - state.updatingInformation = false; - } - ); - /** update account transactions **/ - builder.addCase( - updateAccountTransactionsThunk.fulfilled, - (state: IAccountsState, action: PayloadAction) => { - state.items = state.items.map( - (account) => - action.payload.find((value) => value.id === account.id) || account + + // remove all the updated accounts from the account update list + state.updatingAccounts = state.updatingAccounts.filter( + (accountUpdate) => + !action.payload.find((value) => value.id === accountUpdate.id) ); - state.updatingTransactions = false; } ); builder.addCase( - updateAccountTransactionsThunk.pending, - (state: IAccountsState) => { - state.updatingTransactions = true; + updateAccountsThunk.pending, + (state: IAccountsState, action) => { + // if no account ids, all accounts are being updated + if (!action.meta.arg?.accountIds) { + state.updatingAccounts = state.items.map((value) => ({ + id: value.id, + information: true, + transactions: !action.meta?.arg?.informationOnly, + })); + + return; + } + + // filter the accounts by the supplied ids + state.updatingAccounts = [ + ...(state.updatingAccounts = state.updatingAccounts.filter( + (accountUpdate) => + !action.meta.arg?.accountIds?.find( + (value) => value === accountUpdate.id + ) + )), + ...(action.meta.arg?.accountIds?.map((value) => ({ + id: value, + information: true, + transactions: !action.meta?.arg?.informationOnly, + })) || []), + ]; } ); builder.addCase( - updateAccountTransactionsThunk.rejected, - (state: IAccountsState) => { - state.updatingTransactions = false; + updateAccountsThunk.rejected, + (state: IAccountsState, action) => { + // if no account ids, no accounts are being updated + if (!action.meta.arg?.accountIds) { + state.updatingAccounts = []; + + return; + } + + // filter the accounts by the supplied ids + state.updatingAccounts = [ + ...(state.updatingAccounts = state.updatingAccounts.filter( + (accountUpdate) => + !action.meta.arg?.accountIds?.find( + (value) => value === accountUpdate.id + ) + )), + ...(action.meta.arg?.accountIds?.map((value) => ({ + id: value, + information: false, + transactions: false, + })) || []), + ]; } ); }, diff --git a/src/extension/features/accounts/thunks/fetchAccountsFromStorageThunk.ts b/src/extension/features/accounts/thunks/fetchAccountsFromStorageThunk.ts index 578e67ad..41f5a44f 100644 --- a/src/extension/features/accounts/thunks/fetchAccountsFromStorageThunk.ts +++ b/src/extension/features/accounts/thunks/fetchAccountsFromStorageThunk.ts @@ -57,7 +57,7 @@ const fetchAccountsFromStorageThunk: AsyncThunk< ).toUpperCase(); // update the account information for selected network - if (options?.updateAccountInformation) { + if (options?.updateInformation) { logger.debug( `${AccountsThunkEnum.FetchAccountsFromStorage}: updating account information for "${selectedNetwork.genesisId}"` ); @@ -67,7 +67,13 @@ const fetchAccountsFromStorageThunk: AsyncThunk< ...account, networkInformation: { ...account.networkInformation, - [encodedGenesisHash]: await updateAccountInformation(account, { + [encodedGenesisHash]: await updateAccountInformation({ + address: AccountService.convertPublicKeyToAlgorandAddress( + account.publicKey + ), + currentAccountInformation: + account.networkInformation[encodedGenesisHash] || + AccountService.initializeDefaultAccountInformation(), delay: index * NODE_REQUEST_DELAY, // delay each request by 100ms from the last one, see https://algonode.io/api/#limits logger, network: selectedNetwork, @@ -81,7 +87,7 @@ const fetchAccountsFromStorageThunk: AsyncThunk< } // update the accounts transactions for selected network - if (options?.updateAccountTransactions) { + if (options?.updateTransactions) { logger.debug( `${AccountsThunkEnum.FetchAccountsFromStorage}: updating account transactions for "${selectedNetwork.genesisId}"` ); @@ -91,7 +97,14 @@ const fetchAccountsFromStorageThunk: AsyncThunk< ...account, networkTransactions: { ...account.networkTransactions, - [encodedGenesisHash]: await updateAccountTransactions(account, { + [encodedGenesisHash]: await updateAccountTransactions({ + address: AccountService.convertPublicKeyToAlgorandAddress( + account.publicKey + ), + currentAccountTransactions: + account.networkTransactions[encodedGenesisHash] || + AccountService.initializeDefaultAccountTransactions(), + delay: index * NODE_REQUEST_DELAY, // delay each request by 100ms from the last one, see https://algonode.io/api/#limits logger, network: selectedNetwork, }), diff --git a/src/extension/features/accounts/thunks/index.ts b/src/extension/features/accounts/thunks/index.ts index a511acf9..5ca5f0c1 100644 --- a/src/extension/features/accounts/thunks/index.ts +++ b/src/extension/features/accounts/thunks/index.ts @@ -3,5 +3,4 @@ export { default as removeAccountByIdThunk } from './removeAccountByIdThunk'; export { default as saveNewAccountThunk } from './saveNewAccountThunk'; export { default as startPollingForAccountInformationThunk } from './startPollingForAccountInformationThunk'; export { default as stopPollingForAccountInformationThunk } from './stopPollingForAccountInformationThunk'; -export { default as updateAccountInformationThunk } from './updateAccountInformationThunk'; -export { default as updateAccountTransactionsThunk } from './updateAccountTransactionsThunk'; +export { default as updateAccountsThunk } from './updateAccountsThunk'; diff --git a/src/extension/features/accounts/thunks/startPollingForAccountInformationThunk.ts b/src/extension/features/accounts/thunks/startPollingForAccountInformationThunk.ts index 9ad27266..38dfa256 100644 --- a/src/extension/features/accounts/thunks/startPollingForAccountInformationThunk.ts +++ b/src/extension/features/accounts/thunks/startPollingForAccountInformationThunk.ts @@ -7,7 +7,7 @@ import { ACCOUNT_INFORMATION_REFRESH_INTERVAL } from '@extension/constants'; import { AccountsThunkEnum } from '@extension/enums'; // thunks -import updateAccountInformationThunk from './updateAccountInformationThunk'; +import updateAccountsThunk from './updateAccountsThunk'; // types import { ILogger } from '@common/types'; @@ -27,7 +27,12 @@ const startPollingForAccountInformationThunk: AsyncThunk< ); return window.setInterval( - () => dispatch(updateAccountInformationThunk()), + () => + dispatch( + updateAccountsThunk({ + informationOnly: true, // only update account information + }) + ), ACCOUNT_INFORMATION_REFRESH_INTERVAL ); // update every 2 minutes } diff --git a/src/extension/features/accounts/thunks/updateAccountInformationThunk.ts b/src/extension/features/accounts/thunks/updateAccountInformationThunk.ts deleted file mode 100644 index dad5b07c..00000000 --- a/src/extension/features/accounts/thunks/updateAccountInformationThunk.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; - -// constants -import { NODE_REQUEST_DELAY } from '@extension/constants'; - -// enums -import { AccountsThunkEnum } from '@extension/enums'; - -// services -import { AccountService } from '@extension/services'; - -// types -import { ILogger } from '@common/types'; -import { - IAccount, - IMainRootState, - INetworkWithTransactionParams, -} from '@extension/types'; -import { IUpdateAccountInformationPayload } from '../types'; - -// utils -import { - convertGenesisHashToHex, - selectNetworkFromSettings, -} from '@extension/utils'; -import { updateAccountInformation } from '../utils'; - -const updateAccountInformationThunk: AsyncThunk< - IAccount[], // return - IUpdateAccountInformationPayload | undefined, // args - Record -> = createAsyncThunk< - IAccount[], - IUpdateAccountInformationPayload | undefined, - { state: IMainRootState } ->( - AccountsThunkEnum.UpdateAccountInformation, - async ( - { accountIds, forceUpdate } = { forceUpdate: false }, - { getState } - ) => { - const logger: ILogger = getState().system.logger; - const networks: INetworkWithTransactionParams[] = getState().networks.items; - const online: boolean = getState().system.online; - const selectedNetwork: INetworkWithTransactionParams | null = - selectNetworkFromSettings(networks, getState().settings); - let accountService: AccountService; - let accounts: IAccount[] = getState().accounts.items; - - if (!online) { - logger.debug( - `${AccountsThunkEnum.UpdateAccountInformation}: the extension appears to be offline, skipping` - ); - - return []; - } - - if (!selectedNetwork) { - logger.debug( - `${AccountsThunkEnum.UpdateAccountInformation}: no network selected, skipping` - ); - - return []; - } - - // if we have account ids, get all the accounts that match - if (accountIds) { - accounts = accounts.filter( - (account) => !!accountIds.find((value) => value === account.id) - ); - } - - accounts = await Promise.all( - accounts.map(async (account, index) => ({ - ...account, - networkInformation: { - ...account.networkInformation, - [convertGenesisHashToHex(selectedNetwork.genesisHash).toUpperCase()]: - await updateAccountInformation(account, { - delay: index * NODE_REQUEST_DELAY, // delay each request by 100ms from the last one, see https://algonode.io/api/#limits - forceUpdate, - logger, - network: selectedNetwork, - }), - }, - })) - ); - accountService = new AccountService({ - logger, - }); - - // save accounts to storage - accounts = await accountService.saveAccounts(accounts); - - return accounts; - } -); - -export default updateAccountInformationThunk; diff --git a/src/extension/features/accounts/thunks/updateAccountTransactionsThunk.ts b/src/extension/features/accounts/thunks/updateAccountTransactionsThunk.ts deleted file mode 100644 index 8dcbe110..00000000 --- a/src/extension/features/accounts/thunks/updateAccountTransactionsThunk.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; - -// constants -import { NODE_REQUEST_DELAY } from '@extension/constants'; - -// enums -import { AccountsThunkEnum } from '@extension/enums'; - -// types -import { ILogger } from '@common/types'; -import { - IAccount, - IMainRootState, - INetworkWithTransactionParams, -} from '@extension/types'; -import { IUpdateAccountTransactionsPayload } from '../types'; - -// utils -import { - convertGenesisHashToHex, - selectNetworkFromSettings, -} from '@extension/utils'; -import { updateAccountTransactions } from '../utils'; - -const updateAccountTransactionsThunk: AsyncThunk< - IAccount[], // return - IUpdateAccountTransactionsPayload | undefined, // args - Record -> = createAsyncThunk< - IAccount[], - IUpdateAccountTransactionsPayload | undefined, - { state: IMainRootState } ->( - AccountsThunkEnum.UpdateAccountTransactions, - async ({ accountIds, refresh } = { refresh: false }, { getState }) => { - const logger: ILogger = getState().system.logger; - const networks: INetworkWithTransactionParams[] = getState().networks.items; - const online: boolean = getState().system.online; - const selectedNetwork: INetworkWithTransactionParams | null = - selectNetworkFromSettings(networks, getState().settings); - let accounts: IAccount[] = getState().accounts.items; - - if (!online) { - logger.debug( - `${AccountsThunkEnum.UpdateAccountTransactions}: the extension appears to be offline, ignoring` - ); - - return []; - } - - if (!selectedNetwork) { - logger.debug( - `${AccountsThunkEnum.UpdateAccountTransactions}: no network selected, ignoring` - ); - - return []; - } - - // if we have account ids, get all the accounts that match - if (accountIds) { - accounts = accounts.filter( - (account) => !!accountIds.find((value) => value === account.id) - ); - } - - return await Promise.all( - accounts.map(async (account, index) => ({ - ...account, - networkTransactions: { - ...account.networkTransactions, - [convertGenesisHashToHex(selectedNetwork.genesisHash).toUpperCase()]: - await updateAccountTransactions(account, { - delay: index * NODE_REQUEST_DELAY, // delay each request by 100ms from the last one, see https://algonode.io/api/#limits - logger, - network: selectedNetwork, - refresh, - }), - }, - })) - ); - } -); - -export default updateAccountTransactionsThunk; diff --git a/src/extension/features/accounts/thunks/updateAccountsThunk.ts b/src/extension/features/accounts/thunks/updateAccountsThunk.ts new file mode 100644 index 00000000..1d385d29 --- /dev/null +++ b/src/extension/features/accounts/thunks/updateAccountsThunk.ts @@ -0,0 +1,141 @@ +import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit'; + +// constants +import { NODE_REQUEST_DELAY } from '@extension/constants'; + +// enums +import { AccountsThunkEnum } from '@extension/enums'; + +// services +import { AccountService } from '@extension/services'; + +// types +import { ILogger } from '@common/types'; +import { + IAccount, + IMainRootState, + INetworkWithTransactionParams, +} from '@extension/types'; +import { IUpdateAccountsPayload } from '../types'; + +// utils +import { + convertGenesisHashToHex, + selectNetworkFromSettings, +} from '@extension/utils'; +import { updateAccountInformation, updateAccountTransactions } from '../utils'; + +const updateAccountsThunk: AsyncThunk< + IAccount[], // return + IUpdateAccountsPayload | undefined, // args + Record +> = createAsyncThunk< + IAccount[], + IUpdateAccountsPayload | undefined, + { state: IMainRootState } +>( + AccountsThunkEnum.UpdateAccounts, + async ( + { + accountIds, + forceInformationUpdate, + informationOnly, + refreshTransactions, + } = { + forceInformationUpdate: false, + informationOnly: true, + refreshTransactions: false, + }, + { getState } + ) => { + const logger: ILogger = getState().system.logger; + const networks: INetworkWithTransactionParams[] = getState().networks.items; + const online: boolean = getState().system.online; + const selectedNetwork: INetworkWithTransactionParams | null = + selectNetworkFromSettings(networks, getState().settings); + let accountService: AccountService; + let accounts: IAccount[] = getState().accounts.items; + let encodedGenesisHash: string; + + if (!online) { + logger.debug( + `${AccountsThunkEnum.UpdateAccounts}: the extension appears to be offline, skipping` + ); + + return []; + } + + if (!selectedNetwork) { + logger.debug( + `${AccountsThunkEnum.UpdateAccounts}: no network selected, skipping` + ); + + return []; + } + + // if we have account ids, get all the accounts that match + if (accountIds) { + accounts = accounts.filter( + (account) => !!accountIds.find((value) => value === account.id) + ); + } + + accountService = new AccountService({ + logger, + }); + encodedGenesisHash = convertGenesisHashToHex( + selectedNetwork.genesisHash + ).toUpperCase(); + accounts = await Promise.all( + accounts.map(async (account, index) => ({ + ...account, + networkInformation: { + ...account.networkInformation, + [encodedGenesisHash]: await updateAccountInformation({ + address: AccountService.convertPublicKeyToAlgorandAddress( + account.publicKey + ), + currentAccountInformation: + account.networkInformation[encodedGenesisHash] || + AccountService.initializeDefaultAccountInformation(), + delay: index * NODE_REQUEST_DELAY, // delay each request by 100ms from the last one, see https://algonode.io/api/#limits + forceUpdate: forceInformationUpdate, + logger, + network: selectedNetwork, + }), + }, + })) + ); + + // ignore transaction updates it account information only has been specified + if (!informationOnly) { + accounts = await Promise.all( + accounts.map(async (account, index) => ({ + ...account, + networkTransactions: { + ...account.networkTransactions, + [encodedGenesisHash]: await updateAccountTransactions({ + address: AccountService.convertPublicKeyToAlgorandAddress( + account.publicKey + ), + currentAccountTransactions: + account.networkTransactions[encodedGenesisHash] || + AccountService.initializeDefaultAccountTransactions(), + delay: index * NODE_REQUEST_DELAY, // delay each request by 100ms from the last one, see https://algonode.io/api/#limits + logger, + network: selectedNetwork, + refresh: refreshTransactions, + }), + }, + })) + ); + } + + // save accounts to storage + accounts = await accountService.saveAccounts(accounts); + + return accounts; + } +); + +export default updateAccountsThunk; diff --git a/src/extension/features/accounts/types/IAccountUpdate.ts b/src/extension/features/accounts/types/IAccountUpdate.ts new file mode 100644 index 00000000..dac77d14 --- /dev/null +++ b/src/extension/features/accounts/types/IAccountUpdate.ts @@ -0,0 +1,12 @@ +/** + * @property {string} id - the ID of the account being updated. + * @property {boolean} information - whether the information is being updated. + * @property {boolean} transactions - whether the transactions are being updated. + */ +interface IAccountUpdate { + id: string; + information: boolean; + transactions: boolean; +} + +export default IAccountUpdate; diff --git a/src/extension/features/accounts/types/IAccountsState.ts b/src/extension/features/accounts/types/IAccountsState.ts index 1b9300ce..8a6b2d2c 100644 --- a/src/extension/features/accounts/types/IAccountsState.ts +++ b/src/extension/features/accounts/types/IAccountsState.ts @@ -1,21 +1,20 @@ // types import { IAccount } from '@extension/types'; +import IAccountUpdate from './IAccountUpdate'; /** * @property {boolean} fetching - true when fetching accounts from storage. * @property {IAccount[]} items - all accounts * @property {number | null} pollingId - id of the polling interval. * @property {boolean} saving - true when the account is being saved to storage. - * @property {boolean} updatingInformation - true when updating account information from the network. - * @property {boolean} updatingTransactions - true when updating transactions from the network. + * @property {IAccountUpdate[]} updatingAccounts - a list of accounts being updated. */ interface IAccountsState { fetching: boolean; items: IAccount[]; pollingId: number | null; saving: boolean; - updatingInformation: boolean; - updatingTransactions: boolean; + updatingAccounts: IAccountUpdate[]; } export default IAccountsState; diff --git a/src/extension/features/accounts/types/IFetchAccountsFromStoragePayload.ts b/src/extension/features/accounts/types/IFetchAccountsFromStoragePayload.ts index 189802c3..f7c696df 100644 --- a/src/extension/features/accounts/types/IFetchAccountsFromStoragePayload.ts +++ b/src/extension/features/accounts/types/IFetchAccountsFromStoragePayload.ts @@ -1,11 +1,11 @@ /** - * @property {boolean} updateAccountInformation - [optional] instruct the thunk to also update the account information. - * @property {boolean} updateAccountTransactions - [optional] instruct the thunk to also update the account + * @property {boolean} updateInformation - [optional] instruct the thunk to also update the account information. + * @property {boolean} updateTransactions - [optional] instruct the thunk to also update the account * transactions. */ interface IFetchAccountsFromStoragePayload { - updateAccountInformation?: boolean; - updateAccountTransactions?: boolean; + updateInformation?: boolean; + updateTransactions?: boolean; } export default IFetchAccountsFromStoragePayload; diff --git a/src/extension/features/accounts/types/IUpdateAccountInformationPayload.ts b/src/extension/features/accounts/types/IUpdateAccountInformationPayload.ts deleted file mode 100644 index 57c98d5f..00000000 --- a/src/extension/features/accounts/types/IUpdateAccountInformationPayload.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @property {string[]} accountIds - [optional] a list of account IDs to update. If this is omitted, all accounts are - * updated. - * @property {string} forceUpdate - [optional] forces an account information update regardless of the updatedAt date. - */ -interface IUpdateAccountInformationPayload { - accountIds?: string[]; - forceUpdate?: boolean; -} - -export default IUpdateAccountInformationPayload; diff --git a/src/extension/features/accounts/types/IUpdateAccountTransactionsPayload.ts b/src/extension/features/accounts/types/IUpdateAccountTransactionsPayload.ts deleted file mode 100644 index ae94c40e..00000000 --- a/src/extension/features/accounts/types/IUpdateAccountTransactionsPayload.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @property {string[]} accountIds - [optional] a list of account IDs to update. If this is omitted, all accounts are - * updated. - * @property {boolean} refresh - [optional] if it is a refresh, the account transactions will be refreshed. - */ -interface IUpdateAccountTransactionsPayload { - accountIds?: string[]; - refresh?: boolean; -} - -export default IUpdateAccountTransactionsPayload; diff --git a/src/extension/features/accounts/types/IUpdateAccountsPayload.ts b/src/extension/features/accounts/types/IUpdateAccountsPayload.ts new file mode 100644 index 00000000..e32b5c99 --- /dev/null +++ b/src/extension/features/accounts/types/IUpdateAccountsPayload.ts @@ -0,0 +1,17 @@ +/** + * @property {string[]} accountIds - [optional] a list of account IDs to update. If this is omitted, all accounts are + * updated. + * @property {boolean} forceInformationUpdate - [optional] forces an account information update regardless of the + * updatedAt date. Defaults to false. + * @property {boolean} informationOnly - [optional] only updates the account information. Defaults to true. + * @property {boolean} refreshTransactions - [optional] fetches the latest transactions as opposed to older + * transactions. Defaults to false. + */ +interface IUpdateAccountsPayload { + accountIds?: string[]; + forceInformationUpdate?: boolean; + informationOnly?: boolean; + refreshTransactions?: boolean; +} + +export default IUpdateAccountsPayload; diff --git a/src/extension/features/accounts/types/index.ts b/src/extension/features/accounts/types/index.ts index a10a76d7..5a31bb68 100644 --- a/src/extension/features/accounts/types/index.ts +++ b/src/extension/features/accounts/types/index.ts @@ -1,5 +1,5 @@ export type { default as IAccountsState } from './IAccountsState'; +export type { default as IAccountUpdate } from './IAccountUpdate'; export type { default as IFetchAccountsFromStoragePayload } from './IFetchAccountsFromStoragePayload'; export type { default as ISaveNewAccountPayload } from './ISaveNewAccountPayload'; -export type { default as IUpdateAccountInformationPayload } from './IUpdateAccountInformationPayload'; -export type { default as IUpdateAccountTransactionsPayload } from './IUpdateAccountTransactionsPayload'; +export type { default as IUpdateAccountsPayload } from './IUpdateAccountsPayload'; diff --git a/src/extension/features/accounts/utils/fetchAlgorandAccountTransactionsWithDelay.ts b/src/extension/features/accounts/utils/fetchAlgorandAccountTransactionsWithDelay.ts index 901c73e5..02a959b2 100644 --- a/src/extension/features/accounts/utils/fetchAlgorandAccountTransactionsWithDelay.ts +++ b/src/extension/features/accounts/utils/fetchAlgorandAccountTransactionsWithDelay.ts @@ -6,6 +6,7 @@ import { IAlgorandAccountTransaction } from '@extension/types'; interface IOptions { address: string; + afterTime: number | null; client: Indexer; delay: number; limit: number; @@ -19,6 +20,7 @@ interface IOptions { */ export default async function fetchAlgorandAccountTransactionsWithDelay({ address, + afterTime, client, delay, limit, @@ -32,6 +34,10 @@ export default async function fetchAlgorandAccountTransactionsWithDelay({ try { requestBuilder = client.lookupAccountTransactions(address).limit(limit); + if (afterTime) { + requestBuilder.afterTime(new Date(afterTime).toISOString()); + } + if (next) { requestBuilder.nextToken(next); } diff --git a/src/extension/features/accounts/utils/getInitialState.ts b/src/extension/features/accounts/utils/getInitialState.ts index 82659763..7e66319f 100644 --- a/src/extension/features/accounts/utils/getInitialState.ts +++ b/src/extension/features/accounts/utils/getInitialState.ts @@ -7,7 +7,6 @@ export default function getInitialState(): IAccountsState { items: [], pollingId: null, saving: false, - updatingInformation: false, - updatingTransactions: false, + updatingAccounts: [], }; } diff --git a/src/extension/features/accounts/utils/index.ts b/src/extension/features/accounts/utils/index.ts index 1a5ecd99..b30a1a3f 100644 --- a/src/extension/features/accounts/utils/index.ts +++ b/src/extension/features/accounts/utils/index.ts @@ -1,5 +1,6 @@ export { default as fetchAccountInformationWithDelay } from './fetchAlgorandAccountInformationWithDelay'; export { default as fetchAlgorandAccountTransactionsWithDelay } from './fetchAlgorandAccountTransactionsWithDelay'; export { default as getInitialState } from './getInitialState'; +export { default as refreshTransactions } from './refreshTransactions'; export { default as updateAccountInformation } from './updateAccountInformation'; export { default as updateAccountTransactions } from './updateAccountTransactions'; diff --git a/src/extension/features/accounts/utils/refreshTransactions.ts b/src/extension/features/accounts/utils/refreshTransactions.ts new file mode 100644 index 00000000..eff3bdf2 --- /dev/null +++ b/src/extension/features/accounts/utils/refreshTransactions.ts @@ -0,0 +1,87 @@ +import { Indexer } from 'algosdk'; + +// constants +import { + DEFAULT_TRANSACTION_INDEXER_LIMIT, + NODE_REQUEST_DELAY, +} from '@extension/constants'; + +// types +import { IBaseOptions } from '@common/types'; +import { + IAlgorandAccountTransaction, + INetwork, + ITransactions, +} from '@extension/types'; + +// utils +import { mapAlgorandTransactionToTransaction } from '@extension/utils'; +import fetchAlgorandAccountTransactionsWithDelay from './fetchAlgorandAccountTransactionsWithDelay'; + +interface IOptions extends IBaseOptions { + address: string; + afterTime: number; + client: Indexer; + delay?: number; + next: string | null; + network: INetwork; +} + +/** + * Fetches all latest transactions from a given time. This function runs recursively until the 'next-token' is + * undefined. + * @param {IOptions} options - options needed to get the latest transactions. + * @returns {Promise} the latest transactions from a given time. + */ +export default async function refreshTransactions({ + address, + afterTime, + client, + delay = 0, + logger, + network, + next, +}: IOptions): Promise { + let algorandAccountTransactions: IAlgorandAccountTransaction; + let newestTransactions: ITransactions[]; + + try { + algorandAccountTransactions = + await fetchAlgorandAccountTransactionsWithDelay({ + address, + afterTime, + client, + delay, + limit: DEFAULT_TRANSACTION_INDEXER_LIMIT, + next, + }); + newestTransactions = algorandAccountTransactions.transactions.map( + mapAlgorandTransactionToTransaction + ); + + // if there is still more, recursively get them until there are no more pages (no more next tokens) + if (algorandAccountTransactions['next-token']) { + return [ + ...newestTransactions, // the indexer always returns the newest > oldest + ...(await refreshTransactions({ + address, + afterTime, + client, + delay: NODE_REQUEST_DELAY, // delay each request by 100ms from the last one, see https://algonode.io/api/#limits + logger, + network, + next: algorandAccountTransactions['next-token'], + })), + ]; + } + + return newestTransactions; + } catch (error) { + logger && + logger.error( + `${refreshTransactions.name}: failed to get transactions for "${address}" on ${network.genesisId}: ${error.message}` + ); + + return []; + } +} diff --git a/src/extension/features/accounts/utils/updateAccountInformation.ts b/src/extension/features/accounts/utils/updateAccountInformation.ts index 3432ea18..06afbcd0 100644 --- a/src/extension/features/accounts/utils/updateAccountInformation.ts +++ b/src/extension/features/accounts/utils/updateAccountInformation.ts @@ -3,13 +3,9 @@ import { Algodv2 } from 'algosdk'; // constants import { ACCOUNT_INFORMATION_ANTIQUATED_TIMEOUT } from '@extension/constants'; -// services -import { AccountService } from '@extension/services'; - // types import { IBaseOptions } from '@common/types'; import { - IAccount, IAccountInformation, IAlgorandAccountInformation, INetwork, @@ -17,13 +13,12 @@ import { // utils import { getAlgodClient } from '@common/utils'; -import { - convertGenesisHashToHex, - mapAlgorandAccountInformationToAccount, -} from '@extension/utils'; +import { mapAlgorandAccountInformationToAccount } from '@extension/utils'; import fetchAlgorandAccountInformationWithDelay from './fetchAlgorandAccountInformationWithDelay'; interface IOptions extends IBaseOptions { + address: string; + currentAccountInformation: IAccountInformation; delay?: number; forceUpdate?: boolean; network: INetwork; @@ -31,21 +26,17 @@ interface IOptions extends IBaseOptions { /** * Fetches the account information for a given address. - * @param {IAccount} account - the account. * @param {IOptions} options - options needed to update the account information. * @returns {Promise} the updated account information. */ -export default async function updateAccountInformation( - account: IAccount, - { delay = 0, forceUpdate = false, logger, network }: IOptions -): Promise { - const encodedGenesisHash: string = convertGenesisHashToHex( - network.genesisHash - ); - const accountInformation: IAccountInformation = - account.networkInformation[encodedGenesisHash] || - AccountService.initializeDefaultAccountInformation(); - let address: string; +export default async function updateAccountInformation({ + address, + currentAccountInformation, + delay = 0, + forceUpdate = false, + logger, + network, +}: IOptions): Promise { let algorandAccountInformation: IAlgorandAccountInformation; let client: Algodv2; let updatedAt: Date; @@ -53,21 +44,21 @@ export default async function updateAccountInformation( // if the account information is not out-of-date just return the account if ( !forceUpdate && - accountInformation.updatedAt && - accountInformation.updatedAt + ACCOUNT_INFORMATION_ANTIQUATED_TIMEOUT > + currentAccountInformation.updatedAt && + currentAccountInformation.updatedAt + + ACCOUNT_INFORMATION_ANTIQUATED_TIMEOUT > new Date().getTime() ) { logger && logger.debug( `${updateAccountInformation.name}: last updated "${new Date( - accountInformation.updatedAt + currentAccountInformation.updatedAt ).toString()}", skipping` ); - return accountInformation; + return currentAccountInformation; } - address = AccountService.convertPublicKeyToAlgorandAddress(account.publicKey); client = getAlgodClient(network, { logger, }); @@ -98,7 +89,7 @@ export default async function updateAccountInformation( return mapAlgorandAccountInformationToAccount( algorandAccountInformation, - accountInformation, + currentAccountInformation, updatedAt.getTime() ); } catch (error) { @@ -107,6 +98,6 @@ export default async function updateAccountInformation( `${updateAccountInformation.name}: failed to get account information for "${address}" on ${network.genesisId}: ${error.message}` ); - return accountInformation; + return currentAccountInformation; } } diff --git a/src/extension/features/accounts/utils/updateAccountTransactions.ts b/src/extension/features/accounts/utils/updateAccountTransactions.ts index 882ca796..cbde2fd8 100644 --- a/src/extension/features/accounts/utils/updateAccountTransactions.ts +++ b/src/extension/features/accounts/utils/updateAccountTransactions.ts @@ -1,12 +1,11 @@ import { Indexer } from 'algosdk'; -// services -import { AccountService } from '@extension/services'; +// constants +import { DEFAULT_TRANSACTION_INDEXER_LIMIT } from '@extension/constants'; // types import { IBaseOptions } from '@common/types'; import { - IAccount, IAccountTransactions, IAlgorandAccountTransaction, INetwork, @@ -14,87 +13,92 @@ import { // utils import { getIndexerClient } from '@common/utils'; -import { - convertGenesisHashToHex, - mapAlgorandTransactionToTransaction, -} from '@extension/utils'; +import { mapAlgorandTransactionToTransaction } from '@extension/utils'; import fetchAlgorandAccountTransactionsWithDelay from './fetchAlgorandAccountTransactionsWithDelay'; +import refreshTransactions from './refreshTransactions'; interface IOptions extends IBaseOptions { + address: string; + currentAccountTransactions: IAccountTransactions; delay?: number; network: INetwork; refresh?: boolean; } /** - * Fetches the account information for a given address. - * @param {IAccount} account - the account. - * @param {IOptions} options - options needed to update the account information. - * @returns {Promise} the updated account information. + * Gets the account transactions. + * @param {IOptions} options - options needed to fetch account transactions. + * @returns {Promise} the updated account information. */ -export default async function updateAccountTransactions( - account: IAccount, - { delay = 0, logger, network, refresh = false }: IOptions -): Promise { - const encodedGenesisHash: string = convertGenesisHashToHex( - network.genesisHash - ).toUpperCase(); - const accountTransactions: IAccountTransactions = - account.networkTransactions[encodedGenesisHash] || - AccountService.initializeDefaultAccountTransactions(); - let address: string; +export default async function updateAccountTransactions({ + address, + currentAccountTransactions, + delay = 0, + logger, + network, + refresh = false, +}: IOptions): Promise { + const client: Indexer = getIndexerClient(network, { + logger, + }); let algorandAccountTransaction: IAlgorandAccountTransaction; - let client: Indexer; - let limit: number = 20; // default - let next: string | null = null; + let mostRecentTransactionTime: number; - // if we are not refreshing, we can get the latest from the next token - if (!refresh) { - next = accountTransactions.next; - } + // if it is a refresh, get all the transactions from the most recent transaction + if (refresh && currentAccountTransactions.transactions.length > 0) { + // get the date of the most recent transaction + mostRecentTransactionTime = currentAccountTransactions.transactions.reduce( + (acc, value) => + value.completedAt && value.completedAt > acc ? value.completedAt : acc, + 0 + ); - // if we are refreshing, increase the limit to the number of transactions, but set a hard limit of 100 - if (refresh) { - if (accountTransactions.transactions.length > 0) { - limit = - accountTransactions.transactions.length > limit - ? accountTransactions.transactions.length - : limit; + logger && + logger.debug( + `${ + updateAccountTransactions.name + }: 'refreshing account transactions for "${address}" on "${ + network.genesisId + }" from "${new Date(mostRecentTransactionTime).toString()}"` + ); - if (limit > 100) { - limit = 100; - } - } + return { + ...currentAccountTransactions, + transactions: [ + // get the most recent transactions + ...(await refreshTransactions({ + address, + afterTime: mostRecentTransactionTime, + client, + logger, + network, + next: null, + })), + ...currentAccountTransactions.transactions, + ], + }; } - address = AccountService.convertPublicKeyToAlgorandAddress(account.publicKey); - client = getIndexerClient(network, { - logger, - }); - logger && logger.debug( - `${updateAccountTransactions.name}: ${ - refresh ? 'refreshing' : 'updating' - } account transactions for "${account.id}" on "${network.genesisId}"${ - next ? ` using next-token "${next}"` : '' - }` + `${updateAccountTransactions.name}: 'updating account transactions for "${address}" on "${network.genesisId}"` ); try { algorandAccountTransaction = await fetchAlgorandAccountTransactionsWithDelay({ address, + afterTime: null, client, delay, - limit, - next, + limit: DEFAULT_TRANSACTION_INDEXER_LIMIT, + next: currentAccountTransactions.next, }); return { next: algorandAccountTransaction['next-token'] || null, transactions: [ - ...(!refresh ? accountTransactions.transactions : []), // if it is not refreshing, append the previous transactions + ...currentAccountTransactions.transactions, ...algorandAccountTransaction.transactions.map( mapAlgorandTransactionToTransaction ), @@ -106,6 +110,6 @@ export default async function updateAccountTransactions( `${updateAccountTransactions.name}: failed to get account transactions for "${address}" on ${network.genesisId}: ${error.message}` ); - return accountTransactions; + return currentAccountTransactions; } } diff --git a/src/extension/pages/AccountPage/AccountPage.tsx b/src/extension/pages/AccountPage/AccountPage.tsx index 1c2ee611..35503780 100644 --- a/src/extension/pages/AccountPage/AccountPage.tsx +++ b/src/extension/pages/AccountPage/AccountPage.tsx @@ -56,7 +56,7 @@ import { ADD_ACCOUNT_ROUTE, ACCOUNTS_ROUTE } from '@extension/constants'; // features import { removeAccountByIdThunk, - updateAccountTransactionsThunk, + updateAccountsThunk, } from '@extension/features/accounts'; import { setSettings } from '@extension/features/settings'; import { setConfirm } from '@extension/features/system'; @@ -176,7 +176,7 @@ const AccountPage: FC = () => { const handleActivityScrollEnd = () => { if (account && accountTransactions && accountTransactions.next) { dispatch( - updateAccountTransactionsThunk({ + updateAccountsThunk({ accountIds: [account.id], }) ); @@ -432,7 +432,7 @@ const AccountPage: FC = () => { accountTransactions.transactions.length <= 0 ) { dispatch( - updateAccountTransactionsThunk({ + updateAccountsThunk({ accountIds: [account.id], }) ); diff --git a/src/extension/pages/MainAddAccountRouter/MainAddAccountRouter.tsx b/src/extension/pages/MainAddAccountRouter/MainAddAccountRouter.tsx index 817155c7..32f7fc77 100644 --- a/src/extension/pages/MainAddAccountRouter/MainAddAccountRouter.tsx +++ b/src/extension/pages/MainAddAccountRouter/MainAddAccountRouter.tsx @@ -15,7 +15,7 @@ import { // features import { saveNewAccountThunk, - updateAccountInformationThunk, + updateAccountsThunk, } from '@extension/features/accounts'; // pages @@ -75,6 +75,7 @@ const MainAddAccountRouter: FC = () => { }; useEffect(() => { + let account: IAccount | null; let address: string | null; if (addAccountResult) { @@ -82,21 +83,27 @@ const MainAddAccountRouter: FC = () => { logger, }); - // if the account has been added, navigate to the account and clean up - if ( - address && - accounts.find( - (value) => - AccountService.convertPublicKeyToAlgorandAddress( - value.publicKey - ) === address - ) - ) { - setAddAccountResult(null); - dispatch(updateAccountInformationThunk()); - navigate(`${ACCOUNTS_ROUTE}/${address}`, { - replace: true, - }); + if (address) { + // if the account has been added, navigate to the account and update + account = + accounts.find( + (value) => + AccountService.convertPublicKeyToAlgorandAddress( + value.publicKey + ) === address + ) || null; + + if (account) { + setAddAccountResult(null); + dispatch( + updateAccountsThunk({ + accountIds: [account.id], + }) + ); + navigate(`${ACCOUNTS_ROUTE}/${address}`, { + replace: true, + }); + } } } }, [accounts]); diff --git a/src/extension/selectors/index.ts b/src/extension/selectors/index.ts index 1a069989..8277dcc6 100644 --- a/src/extension/selectors/index.ts +++ b/src/extension/selectors/index.ts @@ -37,8 +37,6 @@ export { default as useSelectSettings } from './useSelectSettings'; export { default as useSelectSideBar } from './useSelectSideBar'; export { default as useSelectSignBytesRequest } from './useSelectSignBytesRequest'; export { default as useSelectSignTxnsRequest } from './useSelectSignTxnsRequest'; -export { default as useSelectUpdatingAccountInformation } from './useSelectUpdatingAccountInformation'; -export { default as useSelectUpdatingAccountTransactions } from './useSelectUpdatingAccountTransactions'; export { default as useSelectUpdatingAssets } from './useSelectUpdatingAssets'; export { default as useSelectWalletConnectModalOpen } from './useSelectWalletConnectModalOpen'; export { default as useSelectWeb3Wallet } from './useSelectWeb3Wallet'; diff --git a/src/extension/selectors/useSelectUpdatingAccountInformation.ts b/src/extension/selectors/useSelectUpdatingAccountInformation.ts deleted file mode 100644 index 1b109fba..00000000 --- a/src/extension/selectors/useSelectUpdatingAccountInformation.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { useSelector } from 'react-redux'; - -// types -import { IMainRootState } from '@extension/types'; - -/** - * Selects the account information fetching state. - * @returns {boolean} true if the account information is being fetched, false otherwise. - */ -export default function useSelectUpdatingAccountInformation(): boolean { - return useSelector( - (state) => state.accounts.updatingInformation - ); -} diff --git a/src/extension/selectors/useSelectUpdatingAccountTransactions.ts b/src/extension/selectors/useSelectUpdatingAccountTransactions.ts deleted file mode 100644 index 865929c5..00000000 --- a/src/extension/selectors/useSelectUpdatingAccountTransactions.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { useSelector } from 'react-redux'; - -// types -import { IMainRootState } from '@extension/types'; - -/** - * Selects the account transactions updating state. - * @returns {boolean} true if the account transactions are being updated, false otherwise. - */ -export default function useSelectUpdatingAccountTransactions(): boolean { - return useSelector( - (state: IMainRootState) => state.accounts.updatingTransactions - ); -}