diff --git a/app/scripts/controllers/mmi-controller.js b/app/scripts/controllers/mmi-controller.js index bfc44a796..6aec42962 100644 --- a/app/scripts/controllers/mmi-controller.js +++ b/app/scripts/controllers/mmi-controller.js @@ -569,7 +569,7 @@ export default class MMIController extends EventEmitter { const mmiDashboardData = await this.handleMmiDashboardData(); const cookieSetUrls = this.mmiConfigurationController.store.mmiConfiguration?.portfolio - ?.cookieSetUrls; + ?.cookieSetUrls || []; setDashboardCookie(mmiDashboardData, cookieSetUrls); } catch (error) { console.error(error); diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index db6f4bba9..b59f78086 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -790,10 +790,26 @@ "@metamask-institutional/extension>@metamask-institutional/custody-controller": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask-institutional/custody-keyring": true, + "@metamask-institutional/extension>@metamask-institutional/custody-keyring": true, "@metamask/obs-store": true } }, + "@metamask-institutional/extension>@metamask-institutional/custody-keyring": { + "globals": { + "console.log": true, + "console.warn": true + }, + "packages": { + "@ethereumjs/tx>@ethereumjs/util": true, + "@metamask-institutional/custody-keyring>@metamask-institutional/configuration-client": true, + "@metamask-institutional/sdk": true, + "@metamask-institutional/sdk>@metamask-institutional/types": true, + "@metamask/obs-store": true, + "browserify>crypto-browserify": true, + "browserify>events": true, + "gulp-sass>lodash.clonedeep": true + } + }, "@metamask-institutional/institutional-features": { "globals": { "chrome.runtime.id": true, diff --git a/package.json b/package.json index 7ab36645e..dd4acae94 100644 --- a/package.json +++ b/package.json @@ -222,7 +222,7 @@ "@material-ui/core": "^4.11.0", "@metamask-institutional/custody-controller": "0.2.6", "@metamask-institutional/custody-keyring": "^0.0.25", - "@metamask-institutional/extension": "^0.2.1", + "@metamask-institutional/extension": "0.3.2", "@metamask-institutional/institutional-features": "^1.1.8", "@metamask-institutional/portfolio-dashboard": "^1.1.3", "@metamask-institutional/rpc-allowlist": "^1.0.0", diff --git a/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js index a71f06580..430f1d4b9 100644 --- a/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js +++ b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js @@ -48,9 +48,8 @@ const CustodyConfirmLink = ({ hideModal }) => { const { custodians } = useSelector(getMMIConfiguration); const { custodianName } = custodyAccountDetails[toChecksumHexAddress(address)] || {}; - const { displayName, iconUrl } = custodians.find( - (item) => item.name === custodianName || {}, - ); + const { displayName, iconUrl } = + custodians.find((item) => item.name === custodianName) || {}; const { url, ethereum, text, action } = useSelector( (state) => state.appState.modal.modalState.props.link || {}, ); diff --git a/ui/components/ui/metafox-logo/horizontal-logo.js b/ui/components/ui/metafox-logo/horizontal-logo.js index f9b9fe830..129870248 100644 --- a/ui/components/ui/metafox-logo/horizontal-logo.js +++ b/ui/components/ui/metafox-logo/horizontal-logo.js @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; +import { ThemeType } from '../../../../shared/constants/preferences'; const LOGO_WIDTH = 162; const LOGO_HEIGHT = 30; @@ -994,6 +995,6 @@ export default function MetaFoxHorizontalLogo({ } MetaFoxHorizontalLogo.propTypes = { - theme: PropTypes.oneOf(['light', 'dark']), + theme: PropTypes.oneOf([ThemeType.light, ThemeType.dark, ThemeType.os]), className: PropTypes.string, }; diff --git a/ui/pages/home/institutional/institutional-home-footer.js b/ui/pages/home/institutional/institutional-home-footer.js index 46e9c07a9..f9873e8a6 100644 --- a/ui/pages/home/institutional/institutional-home-footer.js +++ b/ui/pages/home/institutional/institutional-home-footer.js @@ -50,9 +50,9 @@ const InstitutionalHomeFooter = ({ activitySupportDisplayStyle }) => { InstitutionalHomeFooter.propTypes = { activitySupportDisplayStyle: PropTypes.shape({ justifyContent: PropTypes.string.isRequired, - paddingLeft: PropTypes.string, - marginBottom: PropTypes.string, - marginTop: PropTypes.string, + paddingLeft: PropTypes.number, + marginBottom: PropTypes.number, + marginTop: PropTypes.number, }).isRequired, }; diff --git a/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap b/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap index c8666db9b..525078513 100644 --- a/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap +++ b/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap @@ -90,6 +90,7 @@ exports[`CustodyPage renders CustodyPage 2`] = ` + `; diff --git a/ui/pages/institutional/custody/custody.js b/ui/pages/institutional/custody/custody.js index 2c62d8df6..1d9b1116e 100644 --- a/ui/pages/institutional/custody/custody.js +++ b/ui/pages/institutional/custody/custody.js @@ -8,6 +8,7 @@ import React, { import { useSelector, useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { v4 as uuidv4 } from 'uuid'; +import { isEqual } from 'lodash'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { mmiActionsFactory } from '../../../store/institutional/institution-background'; import { MetaMetricsContext } from '../../../contexts/metametrics'; @@ -42,6 +43,7 @@ import { } from '../../../helpers/constants/routes'; import { getCurrentChainId, getSelectedAddress } from '../../../selectors'; import { getMMIConfiguration } from '../../../selectors/institutional/selectors'; +import { getInstitutionalConnectRequests } from '../../../ducks/institutional/institutional'; import CustodyAccountList from '../connect-custody/account-list'; import JwtUrlForm from '../../../components/institutional/jwt-url-form'; import { @@ -74,14 +76,15 @@ const CustodyPage = () => { const [apiUrl, setApiUrl] = useState(''); const [addNewTokenClicked, setAddNewTokenClicked] = useState(false); const [chainId, setChainId] = useState(parseInt(currentChainId, 16)); - const [connectRequest, setConnectRequest] = useState(undefined); + const connectRequests = useSelector(getInstitutionalConnectRequests, isEqual); const [accounts, setAccounts] = useState(); const address = useSelector(getSelectedAddress); + const connectRequest = connectRequests ? connectRequests[0] : undefined; const custodianButtons = useMemo(() => { const custodianItems = []; - const sortedCustodians = custodians.sort(function (a, b) { + const sortedCustodians = [...custodians].sort(function (a, b) { const nameA = a.name.toLowerCase(); const nameB = b.name.toLowerCase(); @@ -94,14 +97,34 @@ const CustodyPage = () => { return 0; }); + function shouldShowInProduction(custodian) { + return ( + custodian && + 'production' in custodian && + !custodian.production && + process.env.METAMASK_ENVIRONMENT === 'production' + ); + } + + function isHidden(custodian) { + return custodian && 'hidden' in custodian && custodian.hidden; + } + + function isNotSelectedCustodian(custodian) { + return ( + custodian && + 'name' in custodian && + connectRequest && + Object.keys(connectRequest).length && + custodian.name !== selectedCustodianName + ); + } + sortedCustodians.forEach((custodian) => { if ( - (!custodian.production && - process.env.METAMASK_ENVIRONMENT === 'production') || - custodian.hidden || - (connectRequest && - Object.keys(connectRequest).length && - custodian.name !== selectedCustodianName) + shouldShowInProduction(custodian) || + isHidden(custodian) || + isNotSelectedCustodian(custodian) ) { return; } @@ -134,23 +157,27 @@ const CustodyPage = () => { size={BUTTON_SIZES.SM} data-testid="custody-connect-button" onClick={async () => { - const jwtListValue = await dispatch( - mmiActions.getCustodianJWTList(custodian.name), - ); - setSelectedCustodianName(custodian.name); - setSelectedCustodianType(custodian.type); - setSelectedCustodianImage(custodian.iconUrl); - setSelectedCustodianDisplayName(custodian.displayName); - setApiUrl(custodian.apiUrl); - setCurrentJwt(jwtListValue[0] || ''); - setJwtList(jwtListValue); - trackEvent({ - category: MetaMetricsEventCategory.MMI, - event: MetaMetricsEventName.CustodianSelected, - properties: { - custodian: custodian.name, - }, - }); + try { + const jwtListValue = await dispatch( + mmiActions.getCustodianJWTList(custodian.name), + ); + setSelectedCustodianName(custodian.name); + setSelectedCustodianType(custodian.type); + setSelectedCustodianImage(custodian.iconUrl); + setSelectedCustodianDisplayName(custodian.displayName); + setApiUrl(custodian.apiUrl); + setCurrentJwt(jwtListValue[0] || ''); + setJwtList(jwtListValue); + trackEvent({ + category: MetaMetricsEventCategory.MMI, + event: MetaMetricsEventName.CustodianSelected, + properties: { + custodian: custodian.name, + }, + }); + } catch (error) { + console.error('Error:', error); + } }} > {t('select')} @@ -208,58 +235,54 @@ const CustodyPage = () => { useEffect(() => { const fetchConnectRequest = async () => { - const connectRequestValue = await dispatch( - mmiActions.getCustodianConnectRequest(), - ); + try { + if (connectRequest && Object.keys(connectRequest).length) { + const { + token, + environment: custodianName, + service: custodianType, + apiUrl: custodianApiUrl, + } = connectRequest; - if (Object.keys(connectRequestValue).length) { - const { - token, - custodianName, - custodianType, - apiUrl: custodianApiUrl, - } = connectRequestValue; + const custodianToken = + token || (await dispatch(mmiActions.getCustodianToken(address))); - const jwt = - token || (await dispatch(mmiActions.getCustodianToken(address))); - const accountsValue = await dispatch( - mmiActions.getCustodianAccounts( - jwt, - custodianApiUrl, - custodianType, - true, - ), - ); + setCurrentJwt(custodianToken); + setSelectedCustodianType(custodianType); + setSelectedCustodianName(custodianName); + setApiUrl(custodianApiUrl); + setConnectError(''); - setConnectRequest(connectRequestValue); - setCurrentJwt(jwt); - setSelectedCustodianType(custodianType); - setSelectedCustodianName(custodianName); - setApiUrl(custodianApiUrl); - setConnectError(''); - setAccounts(accountsValue); + const accountsValue = await dispatch( + mmiActions.getCustodianAccounts( + custodianToken, + custodianApiUrl, + custodianType, + true, + ), + ); - trackEvent({ - category: MetaMetricsEventCategory.MMI, - event: MetaMetricsEventName.CustodianConnected, - properties: { - custodian: custodianName, - apiUrl, - rpc: Boolean(connectRequest), - }, - }); + setAccounts(accountsValue); + + trackEvent({ + category: MetaMetricsEventCategory.MMI, + event: MetaMetricsEventName.CustodianConnected, + properties: { + custodian: custodianName, + apiUrl, + rpc: Boolean(connectRequest), + }, + }); + } + } catch (error) { + console.error(error); + handleConnectError(error); } }; - const handleFetchConnectRequest = async () => { - try { - setLoading(true); - await fetchConnectRequest(); - setLoading(false); - } catch (error) { - console.error(error); - setLoading(false); - } + const handleFetchConnectRequest = () => { + setLoading(true); + fetchConnectRequest().finally(() => setLoading(false)); }; handleFetchConnectRequest(); @@ -343,8 +366,7 @@ const CustodyPage = () => { {selectError} )} - - {!accounts && !selectedCustodianType ? ( + {!accounts && !selectedCustodianType && ( { - ) : null} + )} {!accounts && selectedCustodianType && ( <>