diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 92166eac28a3..fd0102666ade 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -374,6 +374,25 @@ export default class AppStateController extends EventEmitter { this.store.updateState({ usedNetworks }); } + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + /** + * Set the interactive replacement token with a url and the old refresh token + * + * @param {object} opts + * @param opts.url + * @param opts.oldRefreshToken + * @returns {void} + */ + showInteractiveReplacementTokenBanner({ url, oldRefreshToken }) { + this.store.updateState({ + interactiveReplacementToken: { + url, + oldRefreshToken, + }, + }); + } + + ///: END:ONLY_INCLUDE_IN /** * A setter for the currentPopupId which indicates the id of popup window that's currently active * diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index 23f74b21dfb3..dc4b4ba36b38 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -625,10 +625,21 @@ export default class MetaMetricsController { * @returns {MetaMetricsContext} */ _buildContext(referrer, page = METAMETRICS_BACKGROUND_PAGE_OBJECT) { + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + const mmiProps = {}; + + if (this.extension?.runtime?.id) { + mmiProps.extensionId = this.extension.runtime.id; + } + ///: END:ONLY_INCLUDE_IN + return { app: { name: 'MetaMask Extension', version: this.version, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + ...mmiProps, + ///: END:ONLY_INCLUDE_IN }, userAgent: window.navigator.userAgent, page, @@ -658,6 +669,15 @@ export default class MetaMetricsController { referrer, environmentType = ENVIRONMENT_TYPE_BACKGROUND, } = rawPayload; + + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + const mmiProps = {}; + + if (this.extension?.runtime?.id) { + mmiProps.extensionId = this.extension.runtime.id; + } + ///: END:ONLY_INCLUDE_IN + return { event, messageId: buildUniqueMessageId(rawPayload), @@ -676,6 +696,9 @@ export default class MetaMetricsController { locale: this.locale, chain_id: properties?.chain_id ?? this.chainId, environment_type: environmentType, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + ...mmiProps, + ///: END:ONLY_INCLUDE_IN }, context: this._buildContext(referrer, page), }; @@ -689,6 +712,13 @@ export default class MetaMetricsController { * @returns {MetaMetricsTraits | null} traits that have changed since last update */ _buildUserTraitsObject(metamaskState) { + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + const mmiAccountAddress = + metamaskState.custodyAccountDetails && + Object.keys(metamaskState.custodyAccountDetails).length + ? Object.keys(metamaskState.custodyAccountDetails)[0] + : null; + ///: END:ONLY_INCLUDE_IN const { traits, previousUserTraits } = this.store.getState(); /** @type {MetaMetricsTraits} */ const currentTraits = { @@ -728,6 +758,11 @@ export default class MetaMetricsController { [MetaMetricsUserTrait.DesktopEnabled]: metamaskState.desktopEnabled || false, ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + [MetaMetricsUserTrait.MmiExtensionId]: this.extension?.runtime?.id, + [MetaMetricsUserTrait.MmiAccountAddress]: mmiAccountAddress, + [MetaMetricsUserTrait.MmiIsCustodian]: Boolean(mmiAccountAddress), + ///: END:ONLY_INCLUDE_IN [MetaMetricsUserTrait.SecurityProviders]: metamaskState.transactionSecurityCheckEnabled ? ['opensea'] : [], }; diff --git a/app/scripts/controllers/metametrics.test.js b/app/scripts/controllers/metametrics.test.js index 9e2a415e813a..0f7553ab2618 100644 --- a/app/scripts/controllers/metametrics.test.js +++ b/app/scripts/controllers/metametrics.test.js @@ -23,6 +23,14 @@ const FAKE_CHAIN_ID = '0x1338'; const LOCALE = 'en_US'; const TEST_META_METRICS_ID = '0xabc'; const DUMMY_ACTION_ID = 'DUMMY_ACTION_ID'; +const MOCK_EXTENSION_ID = 'testid'; + +const MOCK_EXTENSION = { + runtime: { + id: MOCK_EXTENSION_ID, + setUninstallURL: () => undefined, + }, +}; const MOCK_TRAITS = { test_boolean: true, @@ -39,7 +47,11 @@ const MOCK_INVALID_TRAITS = { }; const DEFAULT_TEST_CONTEXT = { - app: { name: 'MetaMask Extension', version: VERSION }, + app: { + name: 'MetaMask Extension', + version: VERSION, + extensionId: MOCK_EXTENSION_ID, + }, page: METAMETRICS_BACKGROUND_PAGE_OBJECT, referrer: undefined, userAgent: window.navigator.userAgent, @@ -56,6 +68,7 @@ const DEFAULT_EVENT_PROPERTIES = { revenue: undefined, value: undefined, currency: undefined, + extensionId: MOCK_EXTENSION_ID, ...DEFAULT_SHARED_PROPERTIES, }; @@ -149,6 +162,7 @@ function getMetaMetricsController({ }, events: {}, }, + extension: MOCK_EXTENSION, }); } describe('MetaMetricsController', function () { @@ -973,6 +987,11 @@ describe('MetaMetricsController', function () { [MetaMetricsUserTrait.TokenDetectionEnabled]: true, [MetaMetricsUserTrait.DesktopEnabled]: false, [MetaMetricsUserTrait.SecurityProviders]: [], + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + [MetaMetricsUserTrait.MmiExtensionId]: 'testid', + [MetaMetricsUserTrait.MmiAccountAddress]: null, + [MetaMetricsUserTrait.MmiIsCustodian]: false, + ///: END:ONLY_INCLUDE_IN }); }); diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 64075a154282..ccd2d89eb139 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -1,5 +1,8 @@ import { ObservableStore } from '@metamask/obs-store'; import { normalize as normalizeAddress } from 'eth-sig-util'; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +import { setDashboardCookie } from '@metamask-institutional/portfolio-dashboard'; +///: END:ONLY_INCLUDE_IN import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network'; import { LedgerTransportTypes } from '../../../shared/constants/hardware-wallets'; import { ThemeType } from '../../../shared/constants/preferences'; @@ -69,12 +72,25 @@ export default class PreferencesController { ...opts.initState, }; + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + initState.useTokenDetection = Boolean(process.env.TOKEN_DETECTION_V2); + ///: END:ONLY_INCLUDE_IN + + this.network = opts.network; this._onInfuraIsBlocked = opts.onInfuraIsBlocked; this._onInfuraIsUnblocked = opts.onInfuraIsUnblocked; this.store = new ObservableStore(initState); this.store.setMaxListeners(13); this.tokenListController = opts.tokenListController; + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + this.handleMmiPortfolio = opts.handleMmiPortfolio; + + if (!process.env.IN_TEST) { + this.mmiConfigurationStore = opts.mmiConfigurationStore.getState(); + } + ///: END:ONLY_INCLUDE_IN + this._subscribeToInfuraAvailability(); global.setPreference = (key, value) => { @@ -245,6 +261,10 @@ export default class PreferencesController { return ids; }, {}); + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + this.prepareMmiPortfolio(); + ///: END:ONLY_INCLUDE_IN + this.store.updateState({ identities }); } @@ -269,6 +289,11 @@ export default class PreferencesController { const [selected] = Object.keys(identities); this.setSelectedAddress(selected); } + + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + this.prepareMmiPortfolio(); + ///: END:ONLY_INCLUDE_IN + return address; } @@ -325,6 +350,10 @@ export default class PreferencesController { this.store.updateState({ identities, lostIdentities }); this.addAddresses(addresses); + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + this.prepareMmiPortfolio(); + ///: END:ONLY_INCLUDE_IN + // If the selected account is no longer valid, // select an arbitrary other account: let selected = this.getSelectedAddress(); @@ -505,6 +534,21 @@ export default class PreferencesController { return this.store.getState().disabledRpcMethodPreferences; } + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + async prepareMmiPortfolio() { + if (!process.env.IN_TEST) { + try { + const mmiDashboardData = await this.handleMmiPortfolio(); + const cookieSetUrls = + this.mmiConfigurationStore.mmiConfiguration?.portfolio?.cookieSetUrls; + setDashboardCookie(mmiDashboardData, cookieSetUrls); + } catch (error) { + console.error(error); + } + } + } + ///: END:ONLY_INCLUDE_IN + // // PRIVATE METHODS //