mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
[MMI] Move mmi actions to extension (#18057)
* MMI adds actions and background files to the institution/ folder * MMI lint fix * MMI lint fix * MMI import path fixed to be relative * MMI import path fixed * MMI adds the relative path to isErrorWithMessage * MMI adds the tests for mmi actions * MMI lint fix * adds tests to mmi actions * prettier fix * MMI prettier and adds test * MMI prettier * MMI lint fix * MMI prettier fix * MMI rename folder
This commit is contained in:
parent
ada47802b3
commit
c022d2eb9a
@ -308,6 +308,10 @@ interface DappSuggestedGasFees {
|
|||||||
* An object representing a transaction, in whatever state it is in.
|
* An object representing a transaction, in whatever state it is in.
|
||||||
*/
|
*/
|
||||||
export interface TransactionMeta {
|
export interface TransactionMeta {
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(mmi)
|
||||||
|
custodyStatus: string;
|
||||||
|
custodyId?: string;
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
/**
|
/**
|
||||||
* The block number this transaction was included in. Currently only present
|
* The block number this transaction was included in. Currently only present
|
||||||
* on incoming transactions!
|
* on incoming transactions!
|
||||||
|
@ -86,6 +86,12 @@ import { TxParams } from '../../app/scripts/controllers/transactions/tx-state-ma
|
|||||||
import { CustomGasSettings } from '../../app/scripts/controllers/transactions';
|
import { CustomGasSettings } from '../../app/scripts/controllers/transactions';
|
||||||
import { ThemeType } from '../../shared/constants/preferences';
|
import { ThemeType } from '../../shared/constants/preferences';
|
||||||
import * as actionConstants from './actionConstants';
|
import * as actionConstants from './actionConstants';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(mmi)
|
||||||
|
import {
|
||||||
|
checkForUnapprovedTypedMessages,
|
||||||
|
updateCustodyState,
|
||||||
|
} from './institutional/institution-actions';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
import {
|
import {
|
||||||
generateActionId,
|
generateActionId,
|
||||||
callBackgroundMethod,
|
callBackgroundMethod,
|
||||||
@ -713,6 +719,11 @@ export function signPersonalMsg(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(updateMetamaskState(newState));
|
dispatch(updateMetamaskState(newState));
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(mmi)
|
||||||
|
if (newState.unapprovedTypedMessages) {
|
||||||
|
return checkForUnapprovedTypedMessages(msgData, newState);
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
dispatch(completedTx(msgData.metamaskId));
|
dispatch(completedTx(msgData.metamaskId));
|
||||||
dispatch(closeCurrentNotificationWindow());
|
dispatch(closeCurrentNotificationWindow());
|
||||||
return msgData;
|
return msgData;
|
||||||
@ -840,6 +851,11 @@ export function signTypedMsg(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(updateMetamaskState(newState));
|
dispatch(updateMetamaskState(newState));
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(mmi)
|
||||||
|
if (newState.unapprovedTypedMessages) {
|
||||||
|
return checkForUnapprovedTypedMessages(msgData, newState);
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
dispatch(completedTx(msgData.metamaskId));
|
dispatch(completedTx(msgData.metamaskId));
|
||||||
dispatch(closeCurrentNotificationWindow());
|
dispatch(closeCurrentNotificationWindow());
|
||||||
return msgData;
|
return msgData;
|
||||||
@ -1848,6 +1864,10 @@ export function updateMetamaskState(
|
|||||||
|
|
||||||
dispatch(initializeSendState({ chainHasChanged: true }));
|
dispatch(initializeSendState({ chainHasChanged: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(mmi)
|
||||||
|
updateCustodyState(dispatch, newState, getState());
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
338
ui/store/institutional/institution-actions.test.js
Normal file
338
ui/store/institutional/institution-actions.test.js
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
import sinon from 'sinon';
|
||||||
|
import configureStore from 'redux-mock-store';
|
||||||
|
import thunk from 'redux-thunk';
|
||||||
|
import MetaMaskController from '../../../app/scripts/metamask-controller';
|
||||||
|
import { _setBackgroundConnection } from '../action-queue';
|
||||||
|
import {
|
||||||
|
showInteractiveReplacementTokenModal,
|
||||||
|
showCustodyConfirmLink,
|
||||||
|
checkForUnapprovedTypedMessages,
|
||||||
|
updateCustodyState,
|
||||||
|
} from './institution-actions';
|
||||||
|
|
||||||
|
const middleware = [thunk];
|
||||||
|
const defaultState = {
|
||||||
|
metamask: {
|
||||||
|
currentLocale: 'test',
|
||||||
|
selectedAddress: '0xFirstAddress',
|
||||||
|
provider: { chainId: '0x1' },
|
||||||
|
accounts: {
|
||||||
|
'0xFirstAddress': {
|
||||||
|
balance: '0x0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
identities: {
|
||||||
|
'0xFirstAddress': {},
|
||||||
|
},
|
||||||
|
cachedBalances: {
|
||||||
|
'0x1': {
|
||||||
|
'0xFirstAddress': '0x0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
custodyStatusMaps: {
|
||||||
|
saturn: {
|
||||||
|
signed: {
|
||||||
|
mmStatus: 'signed',
|
||||||
|
shortText: 'signed',
|
||||||
|
longText: 'signed',
|
||||||
|
finished: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
currentNetworkTxList: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
time: 0,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
},
|
||||||
|
custodyId: '0',
|
||||||
|
custodyStatus: 'signed',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
time: 1,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
},
|
||||||
|
custodyId: '1',
|
||||||
|
custodyStatus: 'signed',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
custodyAccountDetails: {
|
||||||
|
'0xAddress': {
|
||||||
|
address: '0xc96348083d806DFfc546b36e05AF1f9452CDAe91',
|
||||||
|
details: 'details',
|
||||||
|
custodyType: 'testCustody - Saturn',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
appState: {
|
||||||
|
modal: {
|
||||||
|
open: true,
|
||||||
|
modalState: {
|
||||||
|
name: 'CUSTODY_CONFIRM_LINK',
|
||||||
|
props: {
|
||||||
|
custodyId: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockStore = (state = defaultState) => configureStore(middleware)(state);
|
||||||
|
const baseMockState = defaultState.metamask;
|
||||||
|
|
||||||
|
describe('#InstitutionActions', () => {
|
||||||
|
let background;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
background = sinon.createStubInstance(MetaMaskController, {
|
||||||
|
getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
sinon.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls showModal with the property name of showInteractiveReplacementTokenModal', async () => {
|
||||||
|
const store = mockStore();
|
||||||
|
|
||||||
|
background.getApi.returns({
|
||||||
|
setFeatureFlag: sinon
|
||||||
|
.stub()
|
||||||
|
.callsFake((_, __, cb) => cb(new Error('error'))),
|
||||||
|
});
|
||||||
|
|
||||||
|
_setBackgroundConnection(background.getApi());
|
||||||
|
|
||||||
|
const expectedActions = [
|
||||||
|
{
|
||||||
|
type: 'UI_MODAL_OPEN',
|
||||||
|
payload: { name: 'INTERACTIVE_REPLACEMENT_TOKEN_MODAL' },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await store.dispatch(showInteractiveReplacementTokenModal());
|
||||||
|
|
||||||
|
expect(store.getActions()).toStrictEqual(expectedActions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls showModal with the property name of showCustodyConfirmLink', async () => {
|
||||||
|
const store = mockStore();
|
||||||
|
|
||||||
|
background.getApi.returns({
|
||||||
|
setFeatureFlag: sinon
|
||||||
|
.stub()
|
||||||
|
.callsFake((_, __, cb) => cb(new Error('error'))),
|
||||||
|
});
|
||||||
|
|
||||||
|
_setBackgroundConnection(background.getApi());
|
||||||
|
|
||||||
|
const expectedActions = [
|
||||||
|
{
|
||||||
|
type: 'UI_MODAL_OPEN',
|
||||||
|
payload: {
|
||||||
|
name: 'CUSTODY_CONFIRM_LINK',
|
||||||
|
link: 'link',
|
||||||
|
address: '0x1',
|
||||||
|
closeNotification: false,
|
||||||
|
custodyId: 'custodyId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await store.dispatch(
|
||||||
|
showCustodyConfirmLink('link', '0x1', false, 'custodyId'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(store.getActions()).toStrictEqual(expectedActions);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#checkForUnapprovedTypedMessages', () => {
|
||||||
|
it('calls checkForUnapprovedTypedMessages and returns the messageData', async () => {
|
||||||
|
const messageData = {
|
||||||
|
id: 1,
|
||||||
|
type: 'tx',
|
||||||
|
msgParams: {
|
||||||
|
metamaskId: 2,
|
||||||
|
data: '0x1',
|
||||||
|
},
|
||||||
|
custodyId: '123',
|
||||||
|
status: 'unapproved',
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
checkForUnapprovedTypedMessages(messageData, {
|
||||||
|
unapprovedTypedMessages: { msg: 'msg' },
|
||||||
|
}),
|
||||||
|
).toBe(messageData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#updateCustodyState', () => {
|
||||||
|
let background;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
background = sinon.createStubInstance(MetaMaskController, {
|
||||||
|
getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
sinon.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls updateCustodyState but returns early undefined', async () => {
|
||||||
|
const store = mockStore();
|
||||||
|
|
||||||
|
background.getApi.returns({
|
||||||
|
setFeatureFlag: sinon
|
||||||
|
.stub()
|
||||||
|
.callsFake((_, __, cb) => cb(new Error('error'))),
|
||||||
|
});
|
||||||
|
|
||||||
|
_setBackgroundConnection(background.getApi());
|
||||||
|
|
||||||
|
const newState = {
|
||||||
|
provider: {
|
||||||
|
nickname: 'mainnet',
|
||||||
|
chainId: '0x1',
|
||||||
|
},
|
||||||
|
featureFlags: {
|
||||||
|
showIncomingTransactions: false,
|
||||||
|
},
|
||||||
|
selectedAddress: '0xAddress',
|
||||||
|
};
|
||||||
|
|
||||||
|
const custodyState = updateCustodyState(store.dispatch, newState, newState);
|
||||||
|
expect(custodyState).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls updateCustodyState and returns the hideModal', async () => {
|
||||||
|
const store = mockStore();
|
||||||
|
|
||||||
|
background.getApi.returns({
|
||||||
|
setFeatureFlag: sinon
|
||||||
|
.stub()
|
||||||
|
.callsFake((_, __, cb) => cb(new Error('error'))),
|
||||||
|
});
|
||||||
|
|
||||||
|
_setBackgroundConnection(background.getApi());
|
||||||
|
|
||||||
|
const newState = {
|
||||||
|
provider: {
|
||||||
|
nickname: 'mainnet',
|
||||||
|
chainId: '0x1',
|
||||||
|
},
|
||||||
|
featureFlags: {
|
||||||
|
showIncomingTransactions: false,
|
||||||
|
},
|
||||||
|
selectedAddress: '0xAddress',
|
||||||
|
currentNetworkTxList: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
time: 0,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
},
|
||||||
|
custodyId: '0',
|
||||||
|
custodyStatus: 'approved',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
time: 1,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
},
|
||||||
|
custodyId: '1',
|
||||||
|
custodyStatus: 'approved',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedActions = [
|
||||||
|
{
|
||||||
|
type: 'UI_MODAL_CLOSE',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
updateCustodyState(store.dispatch, newState, defaultState);
|
||||||
|
|
||||||
|
expect(store.getActions()).toStrictEqual(expectedActions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls updateCustodyState and closes INTERACTIVE_REPLACEMENT_TOKEN_MODAL', async () => {
|
||||||
|
const store = mockStore();
|
||||||
|
|
||||||
|
background.getApi.returns({
|
||||||
|
setFeatureFlag: sinon
|
||||||
|
.stub()
|
||||||
|
.callsFake((_, __, cb) => cb(new Error('error'))),
|
||||||
|
});
|
||||||
|
|
||||||
|
_setBackgroundConnection(background.getApi());
|
||||||
|
|
||||||
|
const newState = {
|
||||||
|
provider: {
|
||||||
|
nickname: 'mainnet',
|
||||||
|
chainId: '0x1',
|
||||||
|
},
|
||||||
|
featureFlags: {
|
||||||
|
showIncomingTransactions: false,
|
||||||
|
},
|
||||||
|
selectedAddress: '0xAddress',
|
||||||
|
currentNetworkTxList: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
time: 0,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
},
|
||||||
|
custodyId: '0',
|
||||||
|
custodyStatus: 'approved',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
time: 1,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
},
|
||||||
|
custodyId: '1',
|
||||||
|
custodyStatus: 'approved',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const customState = {
|
||||||
|
...defaultState,
|
||||||
|
appState: {
|
||||||
|
modal: {
|
||||||
|
open: true,
|
||||||
|
modalState: {
|
||||||
|
name: 'INTERACTIVE_REPLACEMENT_TOKEN_MODAL',
|
||||||
|
props: {
|
||||||
|
custodyId: '1',
|
||||||
|
closeNotification: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const closedNotification = updateCustodyState(
|
||||||
|
store.dispatch,
|
||||||
|
newState,
|
||||||
|
customState,
|
||||||
|
);
|
||||||
|
expect(closedNotification).toBe(undefined);
|
||||||
|
});
|
||||||
|
});
|
130
ui/store/institutional/institution-actions.ts
Normal file
130
ui/store/institutional/institution-actions.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||||
|
import { AnyAction } from 'redux';
|
||||||
|
import {
|
||||||
|
closeCurrentNotificationWindow,
|
||||||
|
hideModal,
|
||||||
|
showModal,
|
||||||
|
} from '../actions';
|
||||||
|
import {
|
||||||
|
CombinedBackgroundAndReduxState,
|
||||||
|
MetaMaskReduxState,
|
||||||
|
TemporaryMessageDataType,
|
||||||
|
} from '../store';
|
||||||
|
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
|
||||||
|
|
||||||
|
export function showInteractiveReplacementTokenModal(): ThunkAction<
|
||||||
|
void,
|
||||||
|
MetaMaskReduxState,
|
||||||
|
unknown,
|
||||||
|
AnyAction
|
||||||
|
> {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(
|
||||||
|
showModal({
|
||||||
|
name: 'INTERACTIVE_REPLACEMENT_TOKEN_MODAL',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showCustodyConfirmLink(
|
||||||
|
link: string,
|
||||||
|
address: string,
|
||||||
|
closeNotification: boolean,
|
||||||
|
custodyId: string,
|
||||||
|
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(
|
||||||
|
showModal({
|
||||||
|
name: 'CUSTODY_CONFIRM_LINK',
|
||||||
|
link,
|
||||||
|
address,
|
||||||
|
closeNotification,
|
||||||
|
custodyId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateCustodyState(
|
||||||
|
dispatch: ThunkDispatch<CombinedBackgroundAndReduxState, unknown, AnyAction>,
|
||||||
|
newState: MetaMaskReduxState['metamask'],
|
||||||
|
state: CombinedBackgroundAndReduxState & any,
|
||||||
|
) {
|
||||||
|
if (!newState.currentNetworkTxList || !state.metamask.currentNetworkTxList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const differentTxs = newState.currentNetworkTxList.filter(
|
||||||
|
(item) =>
|
||||||
|
state.metamask.currentNetworkTxList.filter(
|
||||||
|
(tx: { [key: string]: any }) =>
|
||||||
|
tx.custodyId === item.custodyId &&
|
||||||
|
tx.custodyStatus !== item.custodyStatus,
|
||||||
|
).length > 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
const txStateSaysDeepLinkShouldClose = Boolean(
|
||||||
|
differentTxs.find((tx) => {
|
||||||
|
const custodyAccountDetails =
|
||||||
|
state.metamask.custodyAccountDetails[
|
||||||
|
toChecksumHexAddress(tx.txParams.from)
|
||||||
|
];
|
||||||
|
const custody = custodyAccountDetails?.custodyType
|
||||||
|
.split(' - ')[1]
|
||||||
|
.toLowerCase();
|
||||||
|
if (!custody) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
tx.custodyId === state.appState.modal.modalState.props?.custodyId &&
|
||||||
|
(state.metamask.custodyStatusMaps[custody][tx.custodyStatus]
|
||||||
|
?.mmStatus !== 'approved' ||
|
||||||
|
tx.custodyStatus === 'created')
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
state.appState.modal.open &&
|
||||||
|
state.appState.modal.modalState.name === 'CUSTODY_CONFIRM_LINK' &&
|
||||||
|
txStateSaysDeepLinkShouldClose
|
||||||
|
) {
|
||||||
|
if (state.appState.modal.modalState.props?.closeNotification) {
|
||||||
|
dispatch(closeCurrentNotificationWindow());
|
||||||
|
}
|
||||||
|
dispatch(hideModal());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
state.appState.modal.open &&
|
||||||
|
state.appState.modal.modalState.name ===
|
||||||
|
'INTERACTIVE_REPLACEMENT_TOKEN_MODAL'
|
||||||
|
) {
|
||||||
|
if (state.appState.modal.modalState.props?.closeNotification) {
|
||||||
|
dispatch(closeCurrentNotificationWindow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkForUnapprovedTypedMessages(
|
||||||
|
msgData: TemporaryMessageDataType['msgParams'],
|
||||||
|
newState: MetaMaskReduxState['metamask'],
|
||||||
|
) {
|
||||||
|
const custodianUnapprovedMessages = Object.keys(
|
||||||
|
newState.unapprovedTypedMessages,
|
||||||
|
)
|
||||||
|
.map((key) => newState.unapprovedTypedMessages[key])
|
||||||
|
.filter((message) => message.custodyId && message.status === 'unapproved');
|
||||||
|
|
||||||
|
if (custodianUnapprovedMessages && custodianUnapprovedMessages.length > 0) {
|
||||||
|
return {
|
||||||
|
...msgData,
|
||||||
|
custodyId:
|
||||||
|
newState.unapprovedTypedMessages[msgData.metamaskId]?.custodyId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgData;
|
||||||
|
}
|
125
ui/store/institutional/institution-background.test.js
Normal file
125
ui/store/institutional/institution-background.test.js
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import { mmiActionsFactory } from './institution-background';
|
||||||
|
|
||||||
|
describe('Institution Actions', () => {
|
||||||
|
describe('#mmiActionsFactory', () => {
|
||||||
|
it('returns mmiActions object', async () => {
|
||||||
|
const actionsMock = {
|
||||||
|
connectCustodyAddresses: jest.fn(),
|
||||||
|
getCustodianAccounts: jest.fn(),
|
||||||
|
getCustodianAccountsByAddress: jest.fn(),
|
||||||
|
getCustodianTransactionDeepLink: jest.fn(),
|
||||||
|
getCustodianConfirmDeepLink: jest.fn(),
|
||||||
|
getCustodianSignMessageDeepLink: jest.fn(),
|
||||||
|
getCustodianToken: jest.fn(),
|
||||||
|
getCustodianJWTList: jest.fn(),
|
||||||
|
setComplianceAuthData: jest.fn(),
|
||||||
|
deleteComplianceAuthData: jest.fn(),
|
||||||
|
generateComplianceReport: jest.fn(),
|
||||||
|
getComplianceHistoricalReportsByAddress: jest.fn(),
|
||||||
|
syncReportsInProgress: jest.fn(),
|
||||||
|
removeConnectInstitutionalFeature: jest.fn(),
|
||||||
|
removeAddTokenConnectRequest: jest.fn(),
|
||||||
|
setCustodianConnectRequest: jest.fn(),
|
||||||
|
getCustodianConnectRequest: jest.fn(),
|
||||||
|
getMmiConfiguration: jest.fn(),
|
||||||
|
getAllCustodianAccountsWithToken: jest.fn(),
|
||||||
|
setWaitForConfirmDeepLinkDialog: jest.fn(),
|
||||||
|
setCustodianNewRefreshToken: jest.fn(),
|
||||||
|
};
|
||||||
|
const mmiActions = mmiActionsFactory({
|
||||||
|
log: { debug: jest.fn(), error: jest.fn() },
|
||||||
|
showLoadingIndication: jest.fn(),
|
||||||
|
submitRequestToBackground: jest.fn(() => actionsMock),
|
||||||
|
displayWarning: jest.fn(),
|
||||||
|
hideLoadingIndication: jest.fn(),
|
||||||
|
forceUpdateMetamaskState: jest.fn(),
|
||||||
|
showModal: jest.fn(),
|
||||||
|
callBackgroundMethod: jest.fn(() => actionsMock),
|
||||||
|
});
|
||||||
|
|
||||||
|
const connectCustodyAddresses = mmiActions.connectCustodyAddresses(
|
||||||
|
{},
|
||||||
|
'0xAddress',
|
||||||
|
);
|
||||||
|
mmiActions.getCustodianAccounts(
|
||||||
|
'token',
|
||||||
|
'apiUrl',
|
||||||
|
'custody',
|
||||||
|
'getNonImportedAccounts',
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
mmiActions.getCustodianAccountsByAddress(
|
||||||
|
'jwt',
|
||||||
|
'apiUrl',
|
||||||
|
'address',
|
||||||
|
'custody',
|
||||||
|
{},
|
||||||
|
4,
|
||||||
|
);
|
||||||
|
mmiActions.getMmiConfiguration({
|
||||||
|
portfolio: {
|
||||||
|
enabled: true,
|
||||||
|
url: 'https://portfolio.io',
|
||||||
|
},
|
||||||
|
custodians: [],
|
||||||
|
});
|
||||||
|
mmiActions.getCustodianToken({});
|
||||||
|
mmiActions.getCustodianConnectRequest({
|
||||||
|
token: 'token',
|
||||||
|
custodianType: 'custodianType',
|
||||||
|
custodianName: 'custodianname',
|
||||||
|
apiUrl: undefined,
|
||||||
|
});
|
||||||
|
mmiActions.getCustodianTransactionDeepLink('0xAddress', 'txId');
|
||||||
|
mmiActions.getCustodianConfirmDeepLink('txId');
|
||||||
|
mmiActions.getCustodianSignMessageDeepLink('0xAddress', 'custodyTxId');
|
||||||
|
mmiActions.getCustodianJWTList({});
|
||||||
|
mmiActions.getAllCustodianAccountsWithToken({
|
||||||
|
custodianType: 'custodianType',
|
||||||
|
token: 'token',
|
||||||
|
});
|
||||||
|
mmiActions.setComplianceAuthData({
|
||||||
|
clientId: 'id',
|
||||||
|
projectId: 'projectId',
|
||||||
|
});
|
||||||
|
mmiActions.deleteComplianceAuthData();
|
||||||
|
mmiActions.generateComplianceReport('0xAddress');
|
||||||
|
mmiActions.getComplianceHistoricalReportsByAddress(
|
||||||
|
'0xAddress',
|
||||||
|
'projectId',
|
||||||
|
);
|
||||||
|
mmiActions.syncReportsInProgress({
|
||||||
|
address: '0xAddress',
|
||||||
|
historicalReports: [],
|
||||||
|
});
|
||||||
|
mmiActions.removeConnectInstitutionalFeature({
|
||||||
|
origin: 'origin',
|
||||||
|
projectId: 'projectId',
|
||||||
|
});
|
||||||
|
mmiActions.removeAddTokenConnectRequest({
|
||||||
|
origin: 'origin',
|
||||||
|
apiUrl: 'https://jupiter-custody.codefi.network',
|
||||||
|
token: 'token',
|
||||||
|
});
|
||||||
|
mmiActions.setCustodianConnectRequest({
|
||||||
|
token: 'token',
|
||||||
|
apiUrl: 'https://jupiter-custody.codefi.network',
|
||||||
|
custodianType: 'custodianType',
|
||||||
|
custodianName: 'custodianname',
|
||||||
|
});
|
||||||
|
const setWaitForConfirmDeepLinkDialog =
|
||||||
|
mmiActions.setWaitForConfirmDeepLinkDialog(true);
|
||||||
|
mmiActions.setCustodianNewRefreshToken(
|
||||||
|
'address',
|
||||||
|
'oldAuthDetails',
|
||||||
|
'oldApiUrl',
|
||||||
|
'newAuthDetails',
|
||||||
|
'newApiUrl',
|
||||||
|
);
|
||||||
|
connectCustodyAddresses(jest.fn());
|
||||||
|
setWaitForConfirmDeepLinkDialog(jest.fn());
|
||||||
|
expect(connectCustodyAddresses).toBeDefined();
|
||||||
|
expect(setWaitForConfirmDeepLinkDialog).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
211
ui/store/institutional/institution-background.ts
Normal file
211
ui/store/institutional/institution-background.ts
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
import log from 'loglevel';
|
||||||
|
import { ThunkAction } from 'redux-thunk';
|
||||||
|
import { AnyAction } from 'redux';
|
||||||
|
import {
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
displayWarning,
|
||||||
|
hideLoadingIndication,
|
||||||
|
showLoadingIndication,
|
||||||
|
} from '../actions';
|
||||||
|
import {
|
||||||
|
callBackgroundMethod,
|
||||||
|
submitRequestToBackground,
|
||||||
|
} from '../action-queue';
|
||||||
|
import { MetaMaskReduxState } from '../store';
|
||||||
|
import { isErrorWithMessage } from '../../../shared/modules/error';
|
||||||
|
|
||||||
|
export function showInteractiveReplacementTokenBanner(
|
||||||
|
url: string,
|
||||||
|
oldRefreshToken: string,
|
||||||
|
) {
|
||||||
|
return () => {
|
||||||
|
callBackgroundMethod(
|
||||||
|
'showInteractiveReplacementTokenBanner',
|
||||||
|
[url, oldRefreshToken],
|
||||||
|
(err) => {
|
||||||
|
if (isErrorWithMessage(err)) {
|
||||||
|
throw new Error(err.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory that contains all MMI actions ready to use
|
||||||
|
* Example usage:
|
||||||
|
* const mmiActions = mmiActionsFactory();
|
||||||
|
* mmiActions.connectCustodyAddresses(...)
|
||||||
|
*/
|
||||||
|
export function mmiActionsFactory() {
|
||||||
|
function createAsyncAction(
|
||||||
|
name: string,
|
||||||
|
params: any,
|
||||||
|
useForceUpdateMetamaskState?: any,
|
||||||
|
loadingText?: string,
|
||||||
|
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||||
|
log.debug(`background.${name}`);
|
||||||
|
return async (dispatch) => {
|
||||||
|
if (loadingText) {
|
||||||
|
dispatch(showLoadingIndication(loadingText));
|
||||||
|
}
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = await submitRequestToBackground(name, [...params]);
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(displayWarning(error));
|
||||||
|
if (isErrorWithMessage(error)) {
|
||||||
|
throw new Error(error.message);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadingText) {
|
||||||
|
dispatch(hideLoadingIndication());
|
||||||
|
}
|
||||||
|
if (useForceUpdateMetamaskState) {
|
||||||
|
await forceUpdateMetamaskState(dispatch);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAction(name: string, payload: any) {
|
||||||
|
return () => {
|
||||||
|
callBackgroundMethod(name, [payload], (err) => {
|
||||||
|
if (isErrorWithMessage(err)) {
|
||||||
|
throw new Error(err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
connectCustodyAddresses: (
|
||||||
|
custodianType: string,
|
||||||
|
custodianName: string,
|
||||||
|
newAccounts: string[],
|
||||||
|
) =>
|
||||||
|
createAsyncAction(
|
||||||
|
'connectCustodyAddresses',
|
||||||
|
[custodianType, custodianName, newAccounts],
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
'Looking for your custodian account...',
|
||||||
|
),
|
||||||
|
getCustodianAccounts: (
|
||||||
|
token: string,
|
||||||
|
apiUrl: string,
|
||||||
|
custody: string,
|
||||||
|
getNonImportedAccounts: boolean,
|
||||||
|
) =>
|
||||||
|
createAsyncAction(
|
||||||
|
'getCustodianAccounts',
|
||||||
|
[token, apiUrl, custody, getNonImportedAccounts],
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
'Getting custodian accounts...',
|
||||||
|
),
|
||||||
|
getCustodianAccountsByAddress: (
|
||||||
|
jwt: string,
|
||||||
|
apiUrl: string,
|
||||||
|
address: string,
|
||||||
|
custody: string,
|
||||||
|
) =>
|
||||||
|
createAsyncAction(
|
||||||
|
'getCustodianAccountsByAddress',
|
||||||
|
[jwt, apiUrl, address, custody],
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
'Getting custodian accounts...',
|
||||||
|
),
|
||||||
|
getCustodianTransactionDeepLink: (address: string, txId: string) =>
|
||||||
|
createAsyncAction(
|
||||||
|
'getCustodianTransactionDeepLink',
|
||||||
|
[address, txId],
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
),
|
||||||
|
getCustodianConfirmDeepLink: (txId: string) =>
|
||||||
|
createAsyncAction(
|
||||||
|
'getCustodianConfirmDeepLink',
|
||||||
|
[txId],
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
),
|
||||||
|
getCustodianSignMessageDeepLink: (from: string, custodyTxId: string) =>
|
||||||
|
createAsyncAction(
|
||||||
|
'getCustodianSignMessageDeepLink',
|
||||||
|
[from, custodyTxId],
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
),
|
||||||
|
getCustodianToken: (custody: string) =>
|
||||||
|
createAsyncAction(
|
||||||
|
'getCustodianToken',
|
||||||
|
[custody],
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
),
|
||||||
|
getCustodianJWTList: (custody: string) =>
|
||||||
|
createAsyncAction(
|
||||||
|
'getCustodianJWTList',
|
||||||
|
[custody],
|
||||||
|
forceUpdateMetamaskState,
|
||||||
|
),
|
||||||
|
setWaitForConfirmDeepLinkDialog: (waitForConfirmDeepLinkDialog: boolean) =>
|
||||||
|
createAction(
|
||||||
|
'setWaitForConfirmDeepLinkDialog',
|
||||||
|
waitForConfirmDeepLinkDialog,
|
||||||
|
),
|
||||||
|
setComplianceAuthData: (clientId: string, projectId: string) =>
|
||||||
|
createAsyncAction('setComplianceAuthData', [{ clientId, projectId }]),
|
||||||
|
deleteComplianceAuthData: () =>
|
||||||
|
createAsyncAction('deleteComplianceAuthData', []),
|
||||||
|
generateComplianceReport: (address: string) =>
|
||||||
|
createAction('generateComplianceReport', address),
|
||||||
|
getComplianceHistoricalReportsByAddress: (
|
||||||
|
address: string,
|
||||||
|
projectId: string,
|
||||||
|
) =>
|
||||||
|
createAsyncAction('getComplianceHistoricalReportsByAddress', [
|
||||||
|
address,
|
||||||
|
projectId,
|
||||||
|
]),
|
||||||
|
syncReportsInProgress: (address: string, historicalReports: []) =>
|
||||||
|
createAction('syncReportsInProgress', { address, historicalReports }),
|
||||||
|
removeConnectInstitutionalFeature: (origin: string, projectId: string) =>
|
||||||
|
createAction('removeConnectInstitutionalFeature', { origin, projectId }),
|
||||||
|
removeAddTokenConnectRequest: (
|
||||||
|
origin: string,
|
||||||
|
apiUrl: string,
|
||||||
|
token: string,
|
||||||
|
) =>
|
||||||
|
createAction('removeAddTokenConnectRequest', { origin, apiUrl, token }),
|
||||||
|
setCustodianConnectRequest: (
|
||||||
|
token: string,
|
||||||
|
apiUrl: string,
|
||||||
|
custodianType: string,
|
||||||
|
custodianName: string,
|
||||||
|
) =>
|
||||||
|
createAsyncAction('setCustodianConnectRequest', [
|
||||||
|
{ token, apiUrl, custodianType, custodianName },
|
||||||
|
]),
|
||||||
|
getCustodianConnectRequest: () =>
|
||||||
|
createAsyncAction('getCustodianConnectRequest', []),
|
||||||
|
getMmiConfiguration: () => createAsyncAction('getMmiConfiguration', []),
|
||||||
|
getAllCustodianAccountsWithToken: (custodyType: string, token: string) =>
|
||||||
|
createAsyncAction('getAllCustodianAccountsWithToken', [
|
||||||
|
custodyType,
|
||||||
|
token,
|
||||||
|
]),
|
||||||
|
setCustodianNewRefreshToken: (
|
||||||
|
address: string,
|
||||||
|
oldAuthDetails: string,
|
||||||
|
oldApiUrl: string,
|
||||||
|
newAuthDetails: string,
|
||||||
|
newApiUrl: string,
|
||||||
|
) =>
|
||||||
|
createAsyncAction('setCustodianNewRefreshToken', [
|
||||||
|
address,
|
||||||
|
oldAuthDetails,
|
||||||
|
oldApiUrl,
|
||||||
|
newAuthDetails,
|
||||||
|
newApiUrl,
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
}
|
@ -22,6 +22,10 @@ export interface TemporaryMessageDataType {
|
|||||||
metamaskId: number;
|
metamaskId: number;
|
||||||
data: string;
|
data: string;
|
||||||
};
|
};
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(mmi)
|
||||||
|
custodyId?: string;
|
||||||
|
status?: string;
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MessagesIndexedById {
|
interface MessagesIndexedById {
|
||||||
@ -68,11 +72,14 @@ interface TemporaryBackgroundState {
|
|||||||
};
|
};
|
||||||
gasFeeEstimates: GasFeeEstimates;
|
gasFeeEstimates: GasFeeEstimates;
|
||||||
gasEstimateType: GasEstimateType;
|
gasEstimateType: GasEstimateType;
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(mmi)
|
||||||
|
custodyAccountDetails?: { [key: string]: any };
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
}
|
}
|
||||||
|
|
||||||
type RootReducerReturnType = ReturnType<typeof rootReducer>;
|
type RootReducerReturnType = ReturnType<typeof rootReducer>;
|
||||||
|
|
||||||
type CombinedBackgroundAndReduxState = RootReducerReturnType & {
|
export type CombinedBackgroundAndReduxState = RootReducerReturnType & {
|
||||||
activeTab: {
|
activeTab: {
|
||||||
origin: string;
|
origin: string;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user