diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 02bcf916939e..af9f410cd985 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -53,6 +53,7 @@ export default class AppStateController extends EventEmitter { showAccountBanner: true, trezorModel: null, currentPopupId: undefined, + currentExtensionPopupId: undefined, // This key is only used for checking if the user had set advancedGasFee // prior to Migration 92.3 where we split out the setting to support // multiple networks. @@ -523,6 +524,10 @@ export default class AppStateController extends EventEmitter { }); } + setCurrentExtensionPopupId(currentExtensionPopupId) { + this.store.updateState({ currentExtensionPopupId }); + } + /** * A getter to retrieve currentPopupId saved in the appState */ diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c4f6ccf17cd3..4022fb64a1f4 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3106,6 +3106,8 @@ export default class MetamaskController extends EventEmitter { // AppStateController setLastActiveTime: appStateController.setLastActiveTime.bind(appStateController), + setCurrentExtensionPopupId: + appStateController.setCurrentExtensionPopupId.bind(appStateController), setDefaultHomeActiveTabName: appStateController.setDefaultHomeActiveTabName.bind(appStateController), setConnectedStatusPopoverHasBeenShown: diff --git a/ui/index.js b/ui/index.js index 621b2c7aedf7..f2747a38075e 100644 --- a/ui/index.js +++ b/ui/index.js @@ -21,6 +21,7 @@ import { getSelectedInternalAccount, getUnapprovedTransactions, getNetworkToAutomaticallySwitchTo, + getUseRequestQueue, } from './selectors'; import { ALERT_STATE } from './ducks/alerts'; import { @@ -210,6 +211,18 @@ async function startApp(metamaskState, backgroundConnection, opts) { }, }; + // Register this window as the current popup + // and set in background state + if ( + process.env.MULTICHAIN && + getUseRequestQueue(state) && + getEnvironmentType() === ENVIRONMENT_TYPE_POPUP + ) { + const thisPopupId = Date.now(); + global.metamask.id = thisPopupId; + actions.setCurrentExtensionPopupId(thisPopupId); + } + // start app render(, opts.container); diff --git a/ui/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js index e7ee190fad66..bd70be713c9b 100644 --- a/ui/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -197,6 +197,8 @@ export default class Routes extends Component { neverShowSwitchedNetworkMessage: PropTypes.bool.isRequired, automaticallySwitchNetwork: PropTypes.func.isRequired, unapprovedTransactions: PropTypes.number.isRequired, + currentExtensionPopupId: PropTypes.number, + useRequestQueue: PropTypes.bool, ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) isShowKeyringSnapRemovalResultModal: PropTypes.bool.isRequired, hideShowKeyringSnapRemovalResultModal: PropTypes.func.isRequired, @@ -254,6 +256,7 @@ export default class Routes extends Component { unapprovedTransactions, isUnlocked, } = this.props; + if (theme !== prevProps.theme) { this.setTheme(); } @@ -277,6 +280,18 @@ export default class Routes extends Component { activeTabOrigin, ); } + + // Terminate the popup when another popup is opened + // if the user is using RPC queueing + if ( + useRequestQueue && + process.env.MULTICHAIN && + currentExtensionPopupId !== undefined && + global.metamask.id !== undefined && + currentExtensionPopupId !== global.metamask.id + ) { + window.close(); + } } UNSAFE_componentWillMount() { diff --git a/ui/pages/routes/routes.container.js b/ui/pages/routes/routes.container.js index a36300c75f19..9e4da35ab266 100644 --- a/ui/pages/routes/routes.container.js +++ b/ui/pages/routes/routes.container.js @@ -23,6 +23,7 @@ import { getNeverShowSwitchedNetworkMessage, getNetworkToAutomaticallySwitchTo, getNumberOfAllUnapprovedTransactions, + getUseRequestQueue, } from '../../selectors'; import { lockMetamask, @@ -128,6 +129,9 @@ function mapStateToProps(state) { networkToAutomaticallySwitchTo, unapprovedTransactions: getNumberOfAllUnapprovedTransactions(state), neverShowSwitchedNetworkMessage: getNeverShowSwitchedNetworkMessage(state), + currentExtensionPopupId: state.metamask.currentExtensionPopupId, + useRequestQueue: getUseRequestQueue(state), + ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) isShowKeyringSnapRemovalResultModal: state.appState.showKeyringRemovalSnapModal, diff --git a/ui/store/actions.ts b/ui/store/actions.ts index e5ac12360e09..77ad92c1222c 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -4943,6 +4943,16 @@ export function updateInterfaceState( }) as any; } +/** + * Update the currentPopupid generated when the user opened the popup + * + * @param id - The Snap interface ID. + * @returns Promise Resolved on successfully submitted background request. + */ +export async function setCurrentExtensionPopupId(id: number) { + await submitRequestToBackground('setCurrentExtensionPopupId', [id]); +} + /** * Delete the Snap interface from state. *