1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 09:23:21 +01:00

[MMI] Fix Connect MMI and Deep link Flows (#19881)

* Sending showCustodyConfirmLink as a prop and fixing other issues

* Upgraded MMI extension monrepo and trying to fix the issue

* prevents deeplink from closing

* Fixed styles of Custody view and changed the place of it

* Fixed CI issues

* fixing eslint issues

* Update LavaMoat policies

* fixing tests

* Fixed test

* updated snapshots

* reorder, otherwise it won't make sense

* adds necessary methods

* removes duplicated key value

* updated snapshot

---------

Co-authored-by: Antonio Regadas <antonio.regadas@consensys.net>
Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
Co-authored-by: António Regadas <apregadas@gmail.com>
This commit is contained in:
Albert Olivé 2023-07-13 10:42:08 +02:00 committed by GitHub
parent 4e89c6ca8c
commit b5ece42ca1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 361 additions and 274 deletions

View File

@ -982,6 +982,12 @@
"custodianAccount": {
"message": "Custodian account"
},
"custodianAccountAddedDesc": {
"message": "You can now use your custodian accounts in MetaMask Institutional."
},
"custodianAccountAddedTitle": {
"message": "Selected custodian accounts have been added."
},
"custodianReplaceRefreshTokenChangedFailed": {
"message": "Please go to $1 and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again."
},

View File

@ -815,11 +815,18 @@
},
"packages": {
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask-institutional/custody-controller": true,
"@metamask-institutional/extension>@metamask-institutional/custody-controller": true,
"@metamask-institutional/sdk": true,
"@metamask-institutional/sdk>@metamask-institutional/types": true
}
},
"@metamask-institutional/extension>@metamask-institutional/custody-controller": {
"packages": {
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask-institutional/custody-keyring": true,
"@metamask/obs-store": true
}
},
"@metamask-institutional/institutional-features": {
"globals": {
"chrome.runtime.id": true,

View File

@ -218,7 +218,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.1.3",
"@metamask-institutional/extension": "^0.1.6",
"@metamask-institutional/institutional-features": "^1.1.8",
"@metamask-institutional/portfolio-dashboard": "^1.1.3",
"@metamask-institutional/rpc-allowlist": "^1.0.0",

View File

@ -123,9 +123,10 @@ export default class ConfirmPageContainerContent extends Component {
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
noteComponent && (
<Tab
data-testid="note-tab"
className="confirm-page-container-content__tab"
name={t('note')}
pillText={t('new')}
tabKey="note"
onClick={() => {
this.context.trackEvent({
category: 'Note to trader',

View File

@ -17,7 +17,10 @@ import {
setPersonalMessageInProgress,
} from '../../../store/institutional/institution-background';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { checkForUnapprovedMessages } from '../../../store/institutional/institution-actions';
import {
showCustodyConfirmLink,
checkForUnapprovedMessages,
} from '../../../store/institutional/institution-actions';
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app';
///: END:ONLY_INCLUDE_IN
import {
@ -75,52 +78,6 @@ function mapStateToProps(state, ownProps) {
let mapDispatchToProps = null;
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
function mmiMapDispatchToProps(dispatch) {
const mmiActions = mmiActionsFactory();
return {
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
setMsgInProgress: (msgId) => dispatch(setPersonalMessageInProgress(msgId)),
showCustodianDeepLink: ({
custodyId,
fromAddress,
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
}) =>
showCustodianDeepLink({
dispatch,
mmiActions,
txId: undefined,
fromAddress,
custodyId,
isSignature: true,
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
}),
showTransactionsFailedModal: ({
errorMessage,
closeNotification,
operationFailed,
}) =>
dispatch(
showModal({
name: 'TRANSACTION_FAILED',
errorMessage,
closeNotification,
operationFailed,
}),
),
setWaitForConfirmDeepLinkDialog: (wait) =>
dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)),
goHome: () => dispatch(goHome()),
};
}
mapDispatchToProps = mmiMapDispatchToProps;
///: END:ONLY_INCLUDE_IN
mapDispatchToProps = function (dispatch) {
return {
goHome: () => dispatch(goHome()),
@ -150,6 +107,75 @@ mapDispatchToProps = function (dispatch) {
};
};
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
function mmiMapDispatchToProps(dispatch) {
const mmiActions = mmiActionsFactory();
return {
setMsgInProgress: (msgId) => dispatch(setPersonalMessageInProgress(msgId)),
showCustodianDeepLink: ({
custodyId,
fromAddress,
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
}) =>
showCustodianDeepLink({
dispatch,
mmiActions,
txId: undefined,
fromAddress,
custodyId,
isSignature: true,
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
showCustodyConfirmLink,
}),
showTransactionsFailedModal: ({
errorMessage,
closeNotification,
operationFailed,
}) =>
dispatch(
showModal({
name: 'TRANSACTION_FAILED',
errorMessage,
closeNotification,
operationFailed,
}),
),
setWaitForConfirmDeepLinkDialog: (wait) =>
dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)),
goHome: () => dispatch(goHome()),
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
showRejectTransactionsConfirmationModal: ({
onSubmit,
unapprovedTxCount: messagesCount,
}) => {
return dispatch(
showModal({
name: 'REJECT_TRANSACTIONS',
onSubmit,
unapprovedTxCount: messagesCount,
isRequestType: true,
}),
);
},
completedTx: (txId) => dispatch(completedTx(txId)),
resolvePendingApproval: (id) => {
dispatch(resolvePendingApproval(id));
},
rejectPendingApproval: (id, error) =>
dispatch(rejectPendingApproval(id, error)),
cancelAllApprovals: (messagesList) => {
dispatch(rejectAllMessages(messagesList));
},
};
}
mapDispatchToProps = mmiMapDispatchToProps;
///: END:ONLY_INCLUDE_IN
function mergeProps(stateProps, dispatchProps, ownProps) {
const { txData } = ownProps;

View File

@ -30,7 +30,10 @@ import {
setTypedMessageInProgress,
} from '../../../store/institutional/institution-background';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { checkForUnapprovedMessages } from '../../../store/institutional/institution-actions';
import {
showCustodyConfirmLink,
checkForUnapprovedMessages,
} from '../../../store/institutional/institution-actions';
///: END:ONLY_INCLUDE_IN
import {
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
@ -101,52 +104,6 @@ function mapStateToProps(state, ownProps) {
let mapDispatchToProps = null;
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
function mmiMapDispatchToProps(dispatch) {
const mmiActions = mmiActionsFactory();
return {
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
setMsgInProgress: (msgId) => dispatch(setTypedMessageInProgress(msgId)),
showCustodianDeepLink: ({
custodyId,
fromAddress,
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
}) =>
showCustodianDeepLink({
dispatch,
mmiActions,
txId: undefined,
fromAddress,
custodyId,
isSignature: true,
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
}),
showTransactionsFailedModal: ({
errorMessage,
closeNotification,
operationFailed,
}) =>
dispatch(
showModal({
name: 'TRANSACTION_FAILED',
errorMessage,
closeNotification,
operationFailed,
}),
),
setWaitForConfirmDeepLinkDialog: (wait) =>
dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)),
goHome: () => dispatch(goHome()),
};
}
mapDispatchToProps = mmiMapDispatchToProps;
///: END:ONLY_INCLUDE_IN
mapDispatchToProps = function (dispatch) {
return {
resolvePendingApproval: (id) => dispatch(resolvePendingApproval(id)),
@ -173,6 +130,73 @@ mapDispatchToProps = function (dispatch) {
};
};
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
function mmiMapDispatchToProps(dispatch) {
const mmiActions = mmiActionsFactory();
return {
setMsgInProgress: (msgId) => dispatch(setTypedMessageInProgress(msgId)),
showCustodianDeepLink: ({
custodyId,
fromAddress,
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
}) =>
showCustodianDeepLink({
dispatch,
mmiActions,
txId: undefined,
fromAddress,
custodyId,
isSignature: true,
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
showCustodyConfirmLink,
}),
showTransactionsFailedModal: ({
errorMessage,
closeNotification,
operationFailed,
}) =>
dispatch(
showModal({
name: 'TRANSACTION_FAILED',
errorMessage,
closeNotification,
operationFailed,
}),
),
setWaitForConfirmDeepLinkDialog: (wait) =>
dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)),
goHome: () => dispatch(goHome()),
resolvePendingApproval: (id) => dispatch(resolvePendingApproval(id)),
completedTx: (id) => dispatch(completedTx(id)),
rejectPendingApproval: (id, error) =>
dispatch(rejectPendingApproval(id, error)),
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
showRejectTransactionsConfirmationModal: ({
onSubmit,
unapprovedTxCount: unapprovedMessagesCount,
}) => {
return dispatch(
showModal({
name: 'REJECT_TRANSACTIONS',
onSubmit,
unapprovedTxCount: unapprovedMessagesCount,
isRequestType: true,
}),
);
},
cancelAllApprovals: (unconfirmedMessagesList) => {
dispatch(rejectAllMessages(unconfirmedMessagesList));
},
};
}
mapDispatchToProps = mmiMapDispatchToProps;
///: END:ONLY_INCLUDE_IN
function mergeProps(stateProps, dispatchProps, ownProps) {
const {
allAccounts,

View File

@ -581,7 +581,7 @@ export default class ConfirmTransactionBase extends Component {
});
}
handleCancel() {
async handleCancel() {
const {
txData,
cancelTransaction,
@ -592,9 +592,8 @@ export default class ConfirmTransactionBase extends Component {
this._removeBeforeUnload();
updateCustomNonce('');
cancelTransaction(txData).then(() => {
history.push(mostRecentOverviewPage);
});
await cancelTransaction(txData);
history.push(mostRecentOverviewPage);
}
handleSubmit() {
@ -705,6 +704,7 @@ export default class ConfirmTransactionBase extends Component {
toAccounts,
toAddress,
showCustodianDeepLink,
clearConfirmTransaction,
} = this.props;
const { noteText } = this.state;
@ -761,7 +761,7 @@ export default class ConfirmTransactionBase extends Component {
});
},
onDeepLinkShown: () => {
this.props.clearConfirmTransaction();
clearConfirmTransaction();
this.setState({ submitting: false }, () => {
history.push(mostRecentOverviewPage);
updateCustomNonce('');

View File

@ -76,6 +76,7 @@ import { CUSTOM_GAS_ESTIMATE } from '../../../shared/constants/gas';
import { getAccountType } from '../../selectors/selectors';
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app';
import { getIsNoteToTraderSupported } from '../../selectors/institutional/selectors';
import { showCustodyConfirmLink } from '../../store/institutional/institution-actions';
///: END:ONLY_INCLUDE_IN
import {
TransactionStatus,
@ -330,15 +331,6 @@ export const mapDispatchToProps = (dispatch) => {
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
getCustodianConfirmDeepLink: (id) =>
dispatch(mmiActions.getCustodianConfirmDeepLink(id)),
showCustodyConfirmLink: ({ link, address, closeNotification, custodyId }) =>
dispatch(
mmiActions.showCustodyConfirmLink({
link,
address,
closeNotification,
custodyId,
}),
),
showTransactionsFailedModal: (errorMessage, closeNotification) =>
dispatch(
showModal({
@ -362,6 +354,7 @@ export const mapDispatchToProps = (dispatch) => {
closeNotification,
onDeepLinkFetched,
onDeepLinkShown,
showCustodyConfirmLink,
}),
setWaitForConfirmDeepLinkDialog: (wait) =>
dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)),

View File

@ -234,7 +234,7 @@ describe('Confirm Transaction Base', () => {
store,
);
expect(getByTestId('transaction-note')).toBeInTheDocument();
expect(getByTestId('note-tab')).toBeInTheDocument();
});
it('handleMainSubmit calls sendTransaction correctly', async () => {

View File

@ -1,16 +1,7 @@
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import Box from '../../components/ui/box';
import {
CONNECT_HARDWARE_ROUTE,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
CUSTODY_ACCOUNT_ROUTE,
///: END:ONLY_INCLUDE_IN
} from '../../helpers/constants/routes';
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
import CustodyPage from '../institutional/custody';
///: END:ONLY_INCLUDE_IN
import { CONNECT_HARDWARE_ROUTE } from '../../helpers/constants/routes';
import ConnectHardwareForm from './connect-hardware';
export default function CreateAccountPage() {
@ -22,11 +13,6 @@ export default function CreateAccountPage() {
path={CONNECT_HARDWARE_ROUTE}
component={ConnectHardwareForm}
/>
{
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
<Route exact path={CUSTODY_ACCOUNT_ROUTE} component={CustodyPage} />
///: END:ONLY_INCLUDE_IN
}
</Switch>
</Box>
);

View File

@ -138,7 +138,8 @@ const mapStateToProps = (state) => {
selectedAddress,
firstPermissionsRequestId,
totalUnapprovedCount,
hasApprovalFlows: getApprovalFlows(state).length > 0,
hasApprovalFlows:
Array.isArray(getApprovalFlows) && getApprovalFlows(state).length > 0,
connectedStatusPopoverHasBeenShown,
defaultHomeActiveTabName,
firstTimeFlowType,

View File

@ -168,11 +168,13 @@ const ConfirmAddCustodianToken = () => {
size={BUTTON_SIZES.LG}
data-testid="cancel-btn"
onClick={async () => {
await mmiActions.removeAddTokenConnectRequest({
origin: connectRequest.origin,
apiUrl: connectRequest.apiUrl,
token: connectRequest.token,
});
await dispatch(
mmiActions.removeAddTokenConnectRequest({
origin: connectRequest.origin,
apiUrl: connectRequest.apiUrl,
token: connectRequest.token,
}),
);
trackEvent({
category: 'MMI',
@ -220,11 +222,13 @@ const ConfirmAddCustodianToken = () => {
}),
);
await mmiActions.removeAddTokenConnectRequest({
origin: connectRequest.origin,
apiUrl: connectRequest.apiUrl,
token: connectRequest.token,
});
await dispatch(
mmiActions.removeAddTokenConnectRequest({
origin: connectRequest.origin,
apiUrl: connectRequest.apiUrl,
token: connectRequest.token,
}),
);
trackEvent({
category: 'MMI',

View File

@ -4,6 +4,16 @@ import configureMockStore from 'redux-mock-store';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import ConfirmAddCustodianToken from './confirm-add-custodian-token';
const mockedRemoveAddTokenConnectRequest = jest
.fn()
.mockReturnValue({ type: 'TYPE' });
jest.mock('../../../store/institutional/institution-background', () => ({
mmiActionsFactory: () => ({
removeAddTokenConnectRequest: mockedRemoveAddTokenConnectRequest,
}),
}));
describe('Confirm Add Custodian Token', () => {
const mockStore = {
metamask: {

View File

@ -20,72 +20,75 @@ exports[`CustodyPage renders CustodyPage 1`] = `
exports[`CustodyPage renders CustodyPage 2`] = `
<div>
<div
class="mm-box mm-box--padding-4 mm-box--display-flex mm-box--flex-direction-column mm-box--background-color-background-default"
style="box-shadow: var(--shadow-size-xs) var(--color-shadow-default);"
class="mm-box page-container"
>
<div
class="mm-box mm-box--margin-top-4 mm-box--margin-bottom-4 mm-box--display-flex mm-box--align-items-center"
class="mm-box page-container__content mm-box--padding-4 mm-box--display-flex mm-box--flex-direction-column mm-box--width-full"
>
<button
aria-label="Back"
class="box mm-button-icon mm-button-icon--size-sm box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-icon-default box--background-color-transparent box--rounded-lg"
<div
class="mm-box mm-box--margin-top-4 mm-box--margin-bottom-4 mm-box--display-flex mm-box--align-items-center"
>
<span
class="box mm-icon mm-icon--size-sm box--display-inline-block box--flex-direction-row box--color-inherit"
style="mask-image: url('./images/icons/arrow-left.svg');"
/>
</button>
<p
class="box mm-text mm-text--body-md box--flex-direction-row box--color-text-default"
<button
aria-label="Back"
class="box mm-button-icon mm-button-icon--size-sm box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-icon-default box--background-color-transparent box--rounded-lg"
>
<span
class="box mm-icon mm-icon--size-sm box--display-inline-block box--flex-direction-row box--color-inherit"
style="mask-image: url('./images/icons/arrow-left.svg');"
/>
</button>
<p
class="box mm-text mm-text--body-md box--flex-direction-row box--color-text-default"
>
Back
</p>
</div>
<h4
class="box mm-text mm-text--body-lg-medium box--margin-top-4 box--flex-direction-row box--color-text-default"
>
Back
</p>
</div>
<h4
class="box mm-text mm-text--body-lg-medium box--margin-top-4 box--flex-direction-row box--color-text-default"
>
Custodial Accounts
</h4>
<h6
class="box mm-text mm-text--body-md box--margin-top-2 box--margin-bottom-5 box--flex-direction-row box--color-text-default"
>
Please choose the custodian you want to connect in order to add or refresh a token.
</h6>
<div
class="mm-box"
>
<ul
width="full"
Custodial Accounts
</h4>
<h6
class="box mm-text mm-text--body-md box--margin-top-2 box--margin-bottom-5 box--flex-direction-row box--color-text-default"
>
<div
class="mm-box mm-box--margin-bottom-4 mm-box--padding-4 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between mm-box--align-items-center mm-box--rounded-sm mm-box--border-color-border-default box--border-style-solid box--border-width-1"
Please choose the custodian you want to connect in order to add or refresh a token.
</h6>
<div
class="mm-box"
>
<ul
width="full"
>
<div
class="mm-box mm-box--display-flex mm-box--align-items-center"
class="mm-box mm-box--margin-bottom-4 mm-box--padding-4 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between mm-box--align-items-center mm-box--rounded-sm mm-box--border-color-border-default box--border-style-solid box--border-width-1"
>
<img
alt="Saturn Custody"
height="32"
src="https://saturn-custody-ui.dev.metamask-institutional.io/saturn.svg"
width="32"
/>
<p
class="box mm-text mm-text--body-md box--margin-left-2 box--flex-direction-row box--color-text-default"
<div
class="mm-box mm-box--display-flex mm-box--align-items-center"
>
Saturn Custody
</p>
<img
alt="Saturn Custody"
height="32"
src="https://saturn-custody-ui.dev.metamask-institutional.io/saturn.svg"
width="32"
/>
<p
class="box mm-text mm-text--body-md box--margin-left-2 box--flex-direction-row box--color-text-default"
>
Saturn Custody
</p>
</div>
<button
class="box mm-text mm-button-base mm-button-base--size-sm mm-button-primary mm-text--body-md-medium box--padding-right-4 box--padding-left-4 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-inverse box--background-color-primary-default box--rounded-pill"
data-testid="custody-connect-button"
>
Select
</button>
</div>
<button
class="box mm-text mm-button-base mm-button-base--size-sm mm-button-primary mm-text--body-md-medium box--padding-right-4 box--padding-left-4 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-inverse box--background-color-primary-default box--rounded-pill"
data-testid="custody-connect-button"
>
Select
</button>
</div>
</ul>
</ul>
</div>
</div>
</div>
</div>

View File

@ -259,8 +259,7 @@ const CustodyPage = () => {
if (Object.keys(connectRequestValue).length) {
setConnectRequest(connectRequestValue);
setCurrentJwt(
connectRequestValue.token ||
(await dispatch(mmiActions.getCustodianToken())),
connectRequestValue.token || dispatch(mmiActions.getCustodianToken()),
);
setSelectedCustodianType(connectRequestValue.custodianType);
setSelectedCustodianName(connectRequestValue.custodianName);
@ -345,7 +344,7 @@ const CustodyPage = () => {
}
return (
<>
<Box className="page-container">
{connectError && (
<Text textAlign={TextAlign.Center} marginTop={3} padding={[2, 7, 5]}>
{connectError}
@ -362,10 +361,8 @@ const CustodyPage = () => {
padding={4}
display={Display.Flex}
flexDirection={FlexDirection.Column}
backgroundColor={Color.backgroundDefault}
style={{
boxShadow: 'var(--shadow-size-xs) var(--color-shadow-default)',
}}
className="page-container__content"
width={BlockSize.Full}
>
<Box
display={Display.Flex}
@ -405,10 +402,8 @@ const CustodyPage = () => {
padding={4}
display={Display.Flex}
flexDirection={FlexDirection.Column}
backgroundColor={Color.backgroundDefault}
style={{
boxShadow: 'var(--shadow-size-xs) var(--color-shadow-default)',
}}
className="page-container__content"
width={BlockSize.Full}
>
<Box
display={Display.Flex}
@ -426,19 +421,19 @@ const CustodyPage = () => {
/>
<Text>{t('back')}</Text>
</Box>
<Text as="h4">
{selectedCustodianImage && (
<Box display={Display.Flex} alignItems={AlignItems.center}>
{selectedCustodianImage && (
<img
width={32}
height={32}
src={selectedCustodianImage}
alt={selectedCustodianDisplayName}
/>
)}
<Text marginLeft={2}>{selectedCustodianDisplayName}</Text>
<img
width={32}
height={32}
src={selectedCustodianImage}
alt={selectedCustodianDisplayName}
/>
<Text as="h4" marginLeft={2}>
{selectedCustodianDisplayName}
</Text>
</Box>
</Text>
)}
<Text marginTop={4}>
{t('enterCustodianToken', [selectedCustodianDisplayName])}
</Text>
@ -454,35 +449,37 @@ const CustodyPage = () => {
])}
onUrlChange={(url) => setApiUrl(url)}
/>
<Box
display={Display.Flex}
flexDirection={FlexDirection.Row}
justifyContent={JustifyContent.center}
padding={0}
>
</Box>
</Box>
<Box as="footer" className="page-container__footer" padding={4}>
{loading ? (
<PulseLoader />
) : (
<Box display={Display.Flex} gap={4}>
<Button
block
variant={BUTTON_VARIANT.SECONDARY}
marginRight={4}
size={BUTTON_SIZES.LG}
onClick={() => {
cancelConnectCustodianToken();
}}
block
>
{t('cancel')}
</Button>
<Button
block
data-testid="jwt-form-connect-button"
size={BUTTON_SIZES.LG}
onClick={connect}
disabled={
!selectedCustodianName ||
(addNewTokenClicked && !currentJwt)
}
block
>
{t('connect')}
</Button>
</Box>
</Box>
)}
</Box>
</>
)}
@ -625,6 +622,7 @@ const CustodyPage = () => {
className="custody-accounts-empty__footer"
>
<Button
block
size={BUTTON_SIZES.LG}
type={BUTTON_VARIANT.SECONDARY}
onClick={() => history.push(DEFAULT_ROUTE)}
@ -634,7 +632,7 @@ const CustodyPage = () => {
</Box>
</Box>
)}
</>
</Box>
);
};

View File

@ -57,6 +57,7 @@ import InteractiveReplacementTokenNotification from '../../components/institutio
import ConfirmAddInstitutionalFeature from '../institutional/confirm-add-institutional-feature';
import ConfirmAddCustodianToken from '../institutional/confirm-add-custodian-token';
import InteractiveReplacementTokenPage from '../institutional/interactive-replacement-token-page';
import CustodyPage from '../institutional/custody';
///: END:ONLY_INCLUDE_IN
import {
@ -89,6 +90,7 @@ import {
CONFIRM_INSTITUTIONAL_FEATURE_CONNECT,
CONFIRM_ADD_CUSTODIAN_TOKEN,
INTERACTIVE_REPLACEMENT_TOKEN_PAGE,
CUSTODY_ACCOUNT_ROUTE,
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(snaps)
NOTIFICATIONS_ROUTE,
@ -337,6 +339,11 @@ export default class Routes extends Component {
path={CONFIRM_ADD_CUSTODIAN_TOKEN}
component={ConfirmAddCustodianToken}
/>
<Authenticated
path={CUSTODY_ACCOUNT_ROUTE}
component={CustodyPage}
exact
/>
{
///: END:ONLY_INCLUDE_IN
}

View File

@ -1065,8 +1065,9 @@ export function updateAndApproveTx(
dispatch(completedTx(txMeta.id));
dispatch(hideLoadingIndication());
dispatch(updateCustomNonce(''));
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
dispatch(closeCurrentNotificationWindow());
///: END:ONLY_INCLUDE_IN
return txMeta;
})
.catch((err) => {

View File

@ -146,7 +146,12 @@ describe('#InstitutionActions', () => {
];
await store.dispatch(
showCustodyConfirmLink('link', '0x1', false, 'custodyId'),
showCustodyConfirmLink({
link: 'link',
address: '0x1',
closeNotification: false,
custodyId: 'custodyId',
}),
);
expect(store.getActions()).toStrictEqual(expectedActions);

View File

@ -28,12 +28,17 @@ export function showInteractiveReplacementTokenModal(): ThunkAction<
};
}
export function showCustodyConfirmLink(
link: string,
address: string,
closeNotification: boolean,
custodyId: string,
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
export function showCustodyConfirmLink({
link,
address,
closeNotification,
custodyId,
}: {
link: string;
address: string;
closeNotification: boolean;
custodyId: string;
}): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
return (dispatch) => {
dispatch(
showModal({

View File

@ -106,17 +106,14 @@ export function mmiActionsFactory() {
};
}
function createAction(name: string, payload: any): Promise<void> {
return new Promise((resolve, reject) => {
callBackgroundMethod(name, [payload], (error) => {
if (error) {
reject(error);
return;
function createAction(name: string, payload: any) {
return () => {
callBackgroundMethod(name, [payload], (err) => {
if (isErrorWithMessage(err)) {
throw new Error(err.message);
}
resolve();
});
});
};
}
return {

View File

@ -3693,7 +3693,7 @@ __metadata:
languageName: node
linkType: hard
"@metamask-institutional/custody-controller@npm:0.2.6, @metamask-institutional/custody-controller@npm:^0.2.5":
"@metamask-institutional/custody-controller@npm:0.2.6":
version: 0.2.6
resolution: "@metamask-institutional/custody-controller@npm:0.2.6"
dependencies:
@ -3706,6 +3706,19 @@ __metadata:
languageName: node
linkType: hard
"@metamask-institutional/custody-controller@npm:^0.2.8":
version: 0.2.8
resolution: "@metamask-institutional/custody-controller@npm:0.2.8"
dependencies:
"@ethereumjs/util": ^8.0.5
"@metamask-institutional/custody-keyring": ^0.0.25
"@metamask-institutional/sdk": ^0.1.18
"@metamask-institutional/types": ^1.0.3
"@metamask/obs-store": ^8.0.0
checksum: 5950dd7d6497edd90b17a9265bc2006791a8c2f53c3282bc6f5f85bf92bb794d6ac440bb0019b529fe225c28093471bee9104034b1b977ff6bc5ccb6c6287af7
languageName: node
linkType: hard
"@metamask-institutional/custody-keyring@npm:^0.0.22":
version: 0.0.22
resolution: "@metamask-institutional/custody-keyring@npm:0.0.22"
@ -3738,20 +3751,20 @@ __metadata:
languageName: node
linkType: hard
"@metamask-institutional/extension@npm:^0.1.3":
version: 0.1.3
resolution: "@metamask-institutional/extension@npm:0.1.3"
"@metamask-institutional/extension@npm:^0.1.6":
version: 0.1.6
resolution: "@metamask-institutional/extension@npm:0.1.6"
dependencies:
"@ethereumjs/util": ^8.0.5
"@metamask-institutional/custody-controller": ^0.2.5
"@metamask-institutional/custody-keyring": ^0.0.22
"@metamask-institutional/portfolio-dashboard": ^1.1.3
"@metamask-institutional/sdk": ^0.1.16
"@metamask-institutional/transaction-update": ^0.1.20
"@metamask-institutional/types": ^1.0.2
"@metamask-institutional/custody-controller": ^0.2.8
"@metamask-institutional/custody-keyring": ^0.0.25
"@metamask-institutional/portfolio-dashboard": ^1.4.0
"@metamask-institutional/sdk": ^0.1.18
"@metamask-institutional/transaction-update": ^0.1.23
"@metamask-institutional/types": ^1.0.3
jest-create-mock-instance: ^2.0.0
jest-fetch-mock: 3.0.3
checksum: a9a4d3183b972b992649081f586a9d92e92d5366afb9be445fcdeb0b9afd99e765e6a8ad63abddc0d222a800c1a6b02e847e0f705908581950cf1bc791be50ca
checksum: d62e30658fe6be6c6ee955148bbebf729f13070cb049f0080be3a0e2f97f9ba735fe390ad26855cdb2badcdf2bbc089e2dc9641caf5c1970adceb8e71199384f
languageName: node
linkType: hard
@ -3766,10 +3779,10 @@ __metadata:
languageName: node
linkType: hard
"@metamask-institutional/portfolio-dashboard@npm:^1.1.3":
version: 1.1.3
resolution: "@metamask-institutional/portfolio-dashboard@npm:1.1.3"
checksum: ea5918426372f66c5ba575551658ebf443b77e528317aede5d79a21208718d90e756fa86389c366162a58363b38e8d47bed0ebb27938285705723cfa35295287
"@metamask-institutional/portfolio-dashboard@npm:^1.1.3, @metamask-institutional/portfolio-dashboard@npm:^1.4.0":
version: 1.4.0
resolution: "@metamask-institutional/portfolio-dashboard@npm:1.4.0"
checksum: f6bc1801cd5ea945dacdd3404cb4d2da31049746eff7e5436091d238a4a39abae8522cd58958f3b1bc61a558bac2b1c4f38f024976dcf87025d6b9d51a78fbf0
languageName: node
linkType: hard
@ -3780,7 +3793,7 @@ __metadata:
languageName: node
linkType: hard
"@metamask-institutional/sdk@npm:^0.1.14, @metamask-institutional/sdk@npm:^0.1.15, @metamask-institutional/sdk@npm:^0.1.16, @metamask-institutional/sdk@npm:^0.1.17, @metamask-institutional/sdk@npm:^0.1.18":
"@metamask-institutional/sdk@npm:^0.1.14, @metamask-institutional/sdk@npm:^0.1.15, @metamask-institutional/sdk@npm:^0.1.17, @metamask-institutional/sdk@npm:^0.1.18":
version: 0.1.18
resolution: "@metamask-institutional/sdk@npm:0.1.18"
dependencies:
@ -3801,17 +3814,17 @@ __metadata:
languageName: node
linkType: hard
"@metamask-institutional/transaction-update@npm:^0.1.20, @metamask-institutional/transaction-update@npm:^0.1.21":
version: 0.1.21
resolution: "@metamask-institutional/transaction-update@npm:0.1.21"
"@metamask-institutional/transaction-update@npm:^0.1.21, @metamask-institutional/transaction-update@npm:^0.1.23":
version: 0.1.23
resolution: "@metamask-institutional/transaction-update@npm:0.1.23"
dependencies:
"@metamask-institutional/custody-keyring": ^0.0.22
"@metamask-institutional/sdk": ^0.1.15
"@metamask-institutional/types": ^1.0.2
"@metamask-institutional/websocket-client": ^0.1.23
"@metamask-institutional/custody-keyring": ^0.0.25
"@metamask-institutional/sdk": ^0.1.18
"@metamask-institutional/types": ^1.0.3
"@metamask-institutional/websocket-client": ^0.1.25
"@metamask/obs-store": ^8.0.0
ethereumjs-util: ^7.1.5
checksum: 22190a114279e365cdb89a58ae75c610dfa77e7bca365c85544af5f9d6977da0d0f7410b6acc76defdc08b608f6981a54e4df63b66a2e7fd2cd869ce0cd85945
checksum: 73fad3dde4358f4b4b94dba76775c25dc789570d0ec218a682e206739effa5e6f8a809210743e0f8fdbad58900fee6ea3b8accca6a9f74c7052f2e8a25392163
languageName: node
linkType: hard
@ -3822,15 +3835,15 @@ __metadata:
languageName: node
linkType: hard
"@metamask-institutional/websocket-client@npm:^0.1.23":
version: 0.1.23
resolution: "@metamask-institutional/websocket-client@npm:0.1.23"
"@metamask-institutional/websocket-client@npm:^0.1.25":
version: 0.1.25
resolution: "@metamask-institutional/websocket-client@npm:0.1.25"
dependencies:
"@metamask-institutional/custody-keyring": ^0.0.22
"@metamask-institutional/sdk": ^0.1.15
"@metamask-institutional/types": ^1.0.2
"@metamask-institutional/custody-keyring": ^0.0.25
"@metamask-institutional/sdk": ^0.1.18
"@metamask-institutional/types": ^1.0.3
mock-socket: ^9.2.1
checksum: 7b7f091ab43287aa12bdfb75ff9ffc4b2272f1e404a3eab3a3a962b777ef47d374fd62ec3227023b858ce5cedabc00b06a9efcd973dbd71226049835236cca5d
checksum: f42334200fc46dab5b049330cb42881f8e08952a6ff15fceb9fd561653561de303d756fb9267c97e4bf658bf5e2ae040fb7370319208368049cd0c252bffb0ed
languageName: node
linkType: hard
@ -24625,7 +24638,7 @@ __metadata:
"@material-ui/core": ^4.11.0
"@metamask-institutional/custody-controller": 0.2.6
"@metamask-institutional/custody-keyring": ^0.0.25
"@metamask-institutional/extension": ^0.1.3
"@metamask-institutional/extension": ^0.1.6
"@metamask-institutional/institutional-features": ^1.1.8
"@metamask-institutional/portfolio-dashboard": ^1.1.3
"@metamask-institutional/rpc-allowlist": ^1.0.0