diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index ead76e31deab..92173fc5f72c 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -274,6 +274,9 @@ export const SENTRY_BACKGROUND_STATE = { rates: true, cryptocurrencies: true, }, + QueuedRequestController: { + queuedRequestCount: true, + }, SelectedNetworkController: { domains: false }, SignatureController: { unapprovedMsgCount: true, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index fa839b5af4c0..11463edf3430 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -2305,6 +2305,7 @@ export default class MetamaskController extends EventEmitter { AuthenticationController: this.authenticationController, UserStorageController: this.userStorageController, MetamaskNotificationsController: this.metamaskNotificationsController, + QueuedRequestController: this.queuedRequestController, PushPlatformNotificationsController: this.pushPlatformNotificationsController, ...resetOnRestartStore, diff --git a/test/e2e/default-fixture.js b/test/e2e/default-fixture.js index b3075f3319ca..1ffe75134970 100644 --- a/test/e2e/default-fixture.js +++ b/test/e2e/default-fixture.js @@ -221,6 +221,9 @@ function defaultFixture(inputChainId = CHAIN_IDS.LOCALHOST) { useMultiAccountBalanceChecker: true, useRequestQueue: true, }, + QueuedRequestController: { + queuedRequestCount: 0, + }, SelectedNetworkController: { domains: {}, }, diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index f5873fb4cd6a..7bc15af41969 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -100,6 +100,9 @@ function onboardingFixture() { useMultiAccountBalanceChecker: true, useRequestQueue: true, }, + QueuedRequestController: { + queuedRequestCount: 0, + }, SelectedNetworkController: { domains: {}, }, diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json index a289cf91686a..534d5e4d606a 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json @@ -215,6 +215,9 @@ "selectedAddress": "string" }, "PushPlatformNotificationsController": { "fcmToken": "string" }, + "QueuedRequestController": { + "queuedRequestCount": 0 + }, "SelectedNetworkController": { "domains": "object" }, "SignatureController": { "unapprovedMsgs": "object", diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json index bf36656e159c..7bcbd81bf539 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -81,6 +81,7 @@ "nftsDropdownState": {}, "termsOfUseLastAgreed": "number", "qrHardware": {}, + "queuedRequestCount": 0, "usedNetworks": { "0x1": true, "0x5": true, "0x539": true }, "snapsInstallPrivacyWarningShown": true, "surveyLinkLastClickedOrClosed": "object", diff --git a/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-background-state.json index dd90d1071776..2909bf1d3597 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-background-state.json @@ -131,6 +131,9 @@ "useMultiAccountBalanceChecker": true, "useRequestQueue": true }, + "QueuedRequestController": { + "queuedRequestCount": 0 + }, "SelectedNetworkController": { "domains": "object" }, "SmartTransactionsController": { "smartTransactionsState": { diff --git a/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-ui-state.json index fc4bb1d65eed..b41e6d6333d1 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-before-init-opt-in-ui-state.json @@ -131,6 +131,9 @@ "useMultiAccountBalanceChecker": true, "useRequestQueue": true }, + "QueuedRequestController": { + "queuedRequestCount": 0 + }, "SelectedNetworkController": { "domains": "object" }, "SmartTransactionsController": { "smartTransactionsState": { diff --git a/ui/pages/home/home.component.js b/ui/pages/home/home.component.js index d43616dc230d..7e6cdee606b3 100644 --- a/ui/pages/home/home.component.js +++ b/ui/pages/home/home.component.js @@ -89,7 +89,7 @@ import FlaskHomeFooter from './flask/flask-home-footer.component'; function shouldCloseNotificationPopup({ isNotification, - totalUnapprovedCount, + totalUnapprovedAndQueuedRequestCount, hasApprovalFlows, isSigningQRHardwareTransaction, ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) @@ -97,9 +97,11 @@ function shouldCloseNotificationPopup({ institutionalConnectRequests, ///: END:ONLY_INCLUDE_IF }) { + // we can't use totalUnapproved because there are also queued requests + let shouldClose = isNotification && - totalUnapprovedCount === 0 && + totalUnapprovedAndQueuedRequestCount === 0 && !hasApprovalFlows && !isSigningQRHardwareTransaction; diff --git a/ui/pages/home/home.container.js b/ui/pages/home/home.container.js index 9cec77d196cd..4bfc07468cbc 100644 --- a/ui/pages/home/home.container.js +++ b/ui/pages/home/home.container.js @@ -46,6 +46,7 @@ import { getNewTokensImportedError, hasPendingApprovals, getSelectedInternalAccount, + getQueuedRequestCount, getEditedNetwork, ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) getAccountType, @@ -116,6 +117,9 @@ const mapStateToProps = (state) => { const { address: selectedAddress } = getSelectedInternalAccount(state); const { forgottenPassword } = metamask; const totalUnapprovedCount = getTotalUnapprovedCount(state); + const queuedRequestCount = getQueuedRequestCount(state); + const totalUnapprovedAndQueuedRequestCount = + totalUnapprovedCount + queuedRequestCount; const swapsEnabled = getSwapsFeatureIsLive(state); const pendingConfirmations = getUnapprovedTemplatedConfirmations(state); ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) @@ -177,6 +181,7 @@ const mapStateToProps = (state) => { selectedAddress, firstPermissionsRequestId, totalUnapprovedCount, + totalUnapprovedAndQueuedRequestCount, participateInMetaMetrics, hasApprovalFlows: getApprovalFlows(state)?.length > 0, connectedStatusPopoverHasBeenShown, diff --git a/ui/pages/routes/routes.component.test.js b/ui/pages/routes/routes.component.test.js index fe215e737613..8c7d127c88e1 100644 --- a/ui/pages/routes/routes.component.test.js +++ b/ui/pages/routes/routes.component.test.js @@ -139,6 +139,8 @@ describe('toast display', () => { approvalFlows: [], completedOnboarding: true, usedNetworks: [], + pendingApprovals: {}, + pendingApprovalCount: 0, swapsState: { swapsFeatureIsLive: true }, newPrivacyPolicyToastShownDate: date, }, diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index f89ddb1eddd1..73f4af5637d7 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -775,6 +775,10 @@ export function getTotalUnapprovedCount(state) { return state.metamask.pendingApprovalCount ?? 0; } +export function getQueuedRequestCount(state) { + return state.metamask.queuedRequestCount ?? 0; +} + export function getTotalUnapprovedMessagesCount(state) { const { unapprovedMsgCount = 0, diff --git a/ui/selectors/transactions.js b/ui/selectors/transactions.js index 2bca85ff3b66..7cc75d8ee1af 100644 --- a/ui/selectors/transactions.js +++ b/ui/selectors/transactions.js @@ -618,22 +618,6 @@ export const submittedPendingTransactionsSelector = createSelector( ), ); -const hasUnapprovedTransactionsInCurrentNetwork = (state) => { - const unapprovedTxs = getUnapprovedTransactions(state); - const unapprovedTxRequests = getApprovalRequestsByType( - state, - ApprovalType.Transaction, - ); - - const chainId = getCurrentChainId(state); - - const filteredUnapprovedTxInCurrentNetwork = unapprovedTxRequests.filter( - ({ id }) => unapprovedTxs[id] && unapprovedTxs[id].chainId === chainId, - ); - - return filteredUnapprovedTxInCurrentNetwork.length > 0; -}; - const TRANSACTION_APPROVAL_TYPES = [ ApprovalType.EthDecrypt, ApprovalType.EthGetEncryptionPublicKey, @@ -643,8 +627,12 @@ const TRANSACTION_APPROVAL_TYPES = [ ]; export function hasTransactionPendingApprovals(state) { + const unapprovedTxRequests = getApprovalRequestsByType( + state, + ApprovalType.Transaction, + ); return ( - hasUnapprovedTransactionsInCurrentNetwork(state) || + unapprovedTxRequests.length > 0 || hasPendingApprovals(state, TRANSACTION_APPROVAL_TYPES) ); } diff --git a/ui/selectors/transactions.test.js b/ui/selectors/transactions.test.js index 75fb713bcd48..4339cb8bdbed 100644 --- a/ui/selectors/transactions.test.js +++ b/ui/selectors/transactions.test.js @@ -767,10 +767,10 @@ describe('Transaction Selectors', () => { expect(result).toBe(true); }); - it('should return false if there is a pending transaction on different network', () => { + it('should return true if there is a pending transaction on different network', () => { mockedState.metamask.transactions[0].chainId = 'differentChainId'; const result = hasTransactionPendingApprovals(mockedState); - expect(result).toBe(false); + expect(result).toBe(true); }); it.each([