mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-10-22 11:22:43 +02:00
[MMI] personal sign and sign typed logic (#19892)
* adds missing logic * lint fixes
This commit is contained in:
parent
5d3690aa24
commit
2c22e85947
@ -1467,6 +1467,18 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
this.signatureController.newUnsignedPersonalMessage.bind(
|
this.signatureController.newUnsignedPersonalMessage.bind(
|
||||||
this.signatureController,
|
this.signatureController,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
setTypedMessageInProgress:
|
||||||
|
this.signatureController.setTypedMessageInProgress.bind(
|
||||||
|
this.signatureController,
|
||||||
|
),
|
||||||
|
setPersonalMessageInProgress:
|
||||||
|
this.signatureController.setPersonalMessageInProgress.bind(
|
||||||
|
this.signatureController,
|
||||||
|
),
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
processEncryptionPublicKey:
|
processEncryptionPublicKey:
|
||||||
this.encryptionPublicKeyController.newRequestEncryptionPublicKey.bind(
|
this.encryptionPublicKeyController.newRequestEncryptionPublicKey.bind(
|
||||||
this.encryptionPublicKeyController,
|
this.encryptionPublicKeyController,
|
||||||
|
@ -64,7 +64,10 @@ export default class SignatureRequestOriginal extends Component {
|
|||||||
resolvePendingApproval: PropTypes.func.isRequired,
|
resolvePendingApproval: PropTypes.func.isRequired,
|
||||||
completedTx: PropTypes.func.isRequired,
|
completedTx: PropTypes.func.isRequired,
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
// Used to show a warning if the signing account is not the selected account
|
||||||
|
// Largely relevant for contract wallet custodians
|
||||||
selectedAccount: PropTypes.object,
|
selectedAccount: PropTypes.object,
|
||||||
|
mmiOnSignCallback: PropTypes.func,
|
||||||
///: END:ONLY_INCLUDE_IN
|
///: END:ONLY_INCLUDE_IN
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -262,7 +265,7 @@ export default class SignatureRequestOriginal extends Component {
|
|||||||
clearConfirmTransaction,
|
clearConfirmTransaction,
|
||||||
history,
|
history,
|
||||||
mostRecentOverviewPage,
|
mostRecentOverviewPage,
|
||||||
txData: { type, id },
|
txData,
|
||||||
hardwareWalletRequiresConnection,
|
hardwareWalletRequiresConnection,
|
||||||
rejectPendingApproval,
|
rejectPendingApproval,
|
||||||
resolvePendingApproval,
|
resolvePendingApproval,
|
||||||
@ -275,22 +278,34 @@ export default class SignatureRequestOriginal extends Component {
|
|||||||
submitText={t('sign')}
|
submitText={t('sign')}
|
||||||
onCancel={async () => {
|
onCancel={async () => {
|
||||||
await rejectPendingApproval(
|
await rejectPendingApproval(
|
||||||
id,
|
txData.id,
|
||||||
serializeError(ethErrors.provider.userRejectedRequest()),
|
serializeError(ethErrors.provider.userRejectedRequest()),
|
||||||
);
|
);
|
||||||
clearConfirmTransaction();
|
clearConfirmTransaction();
|
||||||
history.push(mostRecentOverviewPage);
|
history.push(mostRecentOverviewPage);
|
||||||
}}
|
}}
|
||||||
onSubmit={async () => {
|
onSubmit={async () => {
|
||||||
if (type === MESSAGE_TYPE.ETH_SIGN) {
|
if (txData.type === MESSAGE_TYPE.ETH_SIGN) {
|
||||||
this.setState({ showSignatureRequestWarning: true });
|
this.setState({ showSignatureRequestWarning: true });
|
||||||
} else {
|
} else {
|
||||||
await resolvePendingApproval(id);
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
if (this.props.mmiOnSignCallback) {
|
||||||
|
await this.props.mmiOnSignCallback(txData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
|
await resolvePendingApproval(txData.id);
|
||||||
clearConfirmTransaction();
|
clearConfirmTransaction();
|
||||||
history.push(mostRecentOverviewPage);
|
history.push(mostRecentOverviewPage);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={hardwareWalletRequiresConnection}
|
disabled={
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
Boolean(txData?.custodyId) ||
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
hardwareWalletRequiresConnection
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,17 @@ import {
|
|||||||
rejectAllMessages,
|
rejectAllMessages,
|
||||||
completedTx,
|
completedTx,
|
||||||
} from '../../../store/actions';
|
} from '../../../store/actions';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
// eslint-disable-next-line import/order
|
||||||
|
import { showCustodianDeepLink } from '@metamask-institutional/extension';
|
||||||
|
import {
|
||||||
|
mmiActionsFactory,
|
||||||
|
setPersonalMessageInProgress,
|
||||||
|
} from '../../../store/institutional/institution-background';
|
||||||
|
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
||||||
|
import { checkForUnapprovedMessages } from '../../../store/institutional/institution-actions';
|
||||||
|
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
import {
|
import {
|
||||||
accountsWithSendEtherInfoSelector,
|
accountsWithSendEtherInfoSelector,
|
||||||
getSubjectMetadata,
|
getSubjectMetadata,
|
||||||
@ -16,6 +27,8 @@ import {
|
|||||||
unconfirmedMessagesHashSelector,
|
unconfirmedMessagesHashSelector,
|
||||||
getTotalUnapprovedMessagesCount,
|
getTotalUnapprovedMessagesCount,
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
unapprovedPersonalMsgsSelector,
|
||||||
|
getAccountType,
|
||||||
getSelectedAccount,
|
getSelectedAccount,
|
||||||
///: END:ONLY_INCLUDE_IN
|
///: END:ONLY_INCLUDE_IN
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
@ -30,6 +43,10 @@ function mapStateToProps(state, ownProps) {
|
|||||||
msgParams: { from },
|
msgParams: { from },
|
||||||
} = ownProps.txData;
|
} = ownProps.txData;
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
const envType = getEnvironmentType();
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
const hardwareWalletRequiresConnection =
|
const hardwareWalletRequiresConnection =
|
||||||
doesAddressRequireLedgerHidConnection(state, from);
|
doesAddressRequireLedgerHidConnection(state, from);
|
||||||
const isLedgerWallet = isAddressLedger(state, from);
|
const isLedgerWallet = isAddressLedger(state, from);
|
||||||
@ -48,12 +65,63 @@ function mapStateToProps(state, ownProps) {
|
|||||||
messagesList,
|
messagesList,
|
||||||
messagesCount,
|
messagesCount,
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
accountType: getAccountType(state),
|
||||||
|
isNotification: envType === ENVIRONMENT_TYPE_NOTIFICATION,
|
||||||
selectedAccount: getSelectedAccount(state),
|
selectedAccount: getSelectedAccount(state),
|
||||||
|
unapprovedPersonalMessages: unapprovedPersonalMsgsSelector(state),
|
||||||
///: END:ONLY_INCLUDE_IN
|
///: END:ONLY_INCLUDE_IN
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
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 {
|
return {
|
||||||
goHome: () => dispatch(goHome()),
|
goHome: () => dispatch(goHome()),
|
||||||
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
|
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
|
||||||
@ -80,12 +148,21 @@ function mapDispatchToProps(dispatch) {
|
|||||||
dispatch(rejectAllMessages(messagesList));
|
dispatch(rejectAllMessages(messagesList));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
function mergeProps(stateProps, dispatchProps, ownProps) {
|
function mergeProps(stateProps, dispatchProps, ownProps) {
|
||||||
const { txData } = ownProps;
|
const { txData } = ownProps;
|
||||||
|
|
||||||
const { allAccounts, messagesList, ...otherStateProps } = stateProps;
|
const {
|
||||||
|
allAccounts,
|
||||||
|
messagesList,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
accountType,
|
||||||
|
isNotification,
|
||||||
|
unapprovedPersonalMessages,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
...otherStateProps
|
||||||
|
} = stateProps;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
msgParams: { from },
|
msgParams: { from },
|
||||||
@ -95,6 +172,41 @@ function mergeProps(stateProps, dispatchProps, ownProps) {
|
|||||||
|
|
||||||
const { cancelAllApprovals: dispatchCancelAllApprovals } = dispatchProps;
|
const { cancelAllApprovals: dispatchCancelAllApprovals } = dispatchProps;
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
const mmiOnSignCallback = async (_msgData) => {
|
||||||
|
if (accountType === 'custody') {
|
||||||
|
try {
|
||||||
|
let msgData = _msgData;
|
||||||
|
let id = _msgData.custodyId;
|
||||||
|
if (!_msgData.custodyId) {
|
||||||
|
msgData = checkForUnapprovedMessages(
|
||||||
|
_msgData,
|
||||||
|
unapprovedPersonalMessages,
|
||||||
|
);
|
||||||
|
id = msgData.custodyId;
|
||||||
|
}
|
||||||
|
dispatchProps.showCustodianDeepLink({
|
||||||
|
custodyId: id,
|
||||||
|
fromAddress: fromAccount.address,
|
||||||
|
closeNotification: isNotification,
|
||||||
|
onDeepLinkFetched: () => undefined,
|
||||||
|
onDeepLinkShown: () => undefined,
|
||||||
|
});
|
||||||
|
await dispatchProps.setMsgInProgress(msgData.metamaskId);
|
||||||
|
await dispatchProps.setWaitForConfirmDeepLinkDialog(true);
|
||||||
|
await goHome();
|
||||||
|
} catch (err) {
|
||||||
|
await dispatchProps.setWaitForConfirmDeepLinkDialog(true);
|
||||||
|
await dispatchProps.showTransactionsFailedModal({
|
||||||
|
errorMessage: err.message,
|
||||||
|
closeNotification: true,
|
||||||
|
operationFailed: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...ownProps,
|
...ownProps,
|
||||||
...otherStateProps,
|
...otherStateProps,
|
||||||
@ -103,6 +215,9 @@ function mergeProps(stateProps, dispatchProps, ownProps) {
|
|||||||
txData,
|
txData,
|
||||||
cancelAllApprovals: () =>
|
cancelAllApprovals: () =>
|
||||||
dispatchCancelAllApprovals(valuesFor(messagesList)),
|
dispatchCancelAllApprovals(valuesFor(messagesList)),
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
|
mmiOnSignCallback,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,14 +223,16 @@ export default class SignatureRequest extends PureComponent {
|
|||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
const onSign = async () => {
|
const onSign = async () => {
|
||||||
await resolvePendingApproval(id);
|
|
||||||
completedTx(id);
|
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
if (this.props.mmiOnSignCallback) {
|
if (this.props.mmiOnSignCallback) {
|
||||||
await this.props.mmiOnSignCallback(txData);
|
await this.props.mmiOnSignCallback(txData);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
///: END:ONLY_INCLUDE_IN
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
|
await resolvePendingApproval(id);
|
||||||
|
completedTx(id);
|
||||||
|
|
||||||
trackEvent({
|
trackEvent({
|
||||||
category: MetaMetricsEventCategory.Transactions,
|
category: MetaMetricsEventCategory.Transactions,
|
||||||
event: 'Confirm',
|
event: 'Confirm',
|
||||||
|
@ -30,7 +30,7 @@ import {
|
|||||||
setTypedMessageInProgress,
|
setTypedMessageInProgress,
|
||||||
} from '../../../store/institutional/institution-background';
|
} from '../../../store/institutional/institution-background';
|
||||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
|
||||||
import { checkForUnapprovedTypedMessages } from '../../../store/institutional/institution-actions';
|
import { checkForUnapprovedMessages } from '../../../store/institutional/institution-actions';
|
||||||
///: END:ONLY_INCLUDE_IN
|
///: END:ONLY_INCLUDE_IN
|
||||||
import {
|
import {
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
@ -214,7 +214,7 @@ function mergeProps(stateProps, dispatchProps, ownProps) {
|
|||||||
let msgData = _msgData;
|
let msgData = _msgData;
|
||||||
let id = _msgData.custodyId;
|
let id = _msgData.custodyId;
|
||||||
if (!_msgData.custodyId) {
|
if (!_msgData.custodyId) {
|
||||||
msgData = checkForUnapprovedTypedMessages(
|
msgData = checkForUnapprovedMessages(
|
||||||
_msgData,
|
_msgData,
|
||||||
unapprovedTypedMessages,
|
unapprovedTypedMessages,
|
||||||
);
|
);
|
||||||
|
@ -6,7 +6,7 @@ import { _setBackgroundConnection } from '../action-queue';
|
|||||||
import {
|
import {
|
||||||
showInteractiveReplacementTokenModal,
|
showInteractiveReplacementTokenModal,
|
||||||
showCustodyConfirmLink,
|
showCustodyConfirmLink,
|
||||||
checkForUnapprovedTypedMessages,
|
checkForUnapprovedMessages,
|
||||||
updateCustodyState,
|
updateCustodyState,
|
||||||
} from './institution-actions';
|
} from './institution-actions';
|
||||||
|
|
||||||
@ -153,8 +153,8 @@ describe('#InstitutionActions', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#checkForUnapprovedTypedMessages', () => {
|
describe('#checkForUnapprovedMessages', () => {
|
||||||
it('calls checkForUnapprovedTypedMessages and returns the messageData', async () => {
|
it('calls checkForUnapprovedMessages and returns the messageData', async () => {
|
||||||
const messageData = {
|
const messageData = {
|
||||||
id: 1,
|
id: 1,
|
||||||
type: 'tx',
|
type: 'tx',
|
||||||
@ -166,7 +166,7 @@ describe('#checkForUnapprovedTypedMessages', () => {
|
|||||||
status: 'unapproved',
|
status: 'unapproved',
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(checkForUnapprovedTypedMessages(messageData, { msg: 'msg' })).toBe(
|
expect(checkForUnapprovedMessages(messageData, { msg: 'msg' })).toBe(
|
||||||
messageData,
|
messageData,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -109,18 +109,18 @@ export function updateCustodyState(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkForUnapprovedTypedMessages(
|
export function checkForUnapprovedMessages(
|
||||||
msgData: TemporaryMessageDataType['msgParams'],
|
msgData: TemporaryMessageDataType['msgParams'],
|
||||||
unapprovedTypedMessages: MessagesIndexedById,
|
unapprovedMessages: MessagesIndexedById,
|
||||||
) {
|
) {
|
||||||
const custodianUnapprovedMessages = Object.keys(unapprovedTypedMessages)
|
const custodianUnapprovedMessages = Object.keys(unapprovedMessages)
|
||||||
.map((key) => unapprovedTypedMessages[key])
|
.map((key) => unapprovedMessages[key])
|
||||||
.filter((message) => message.custodyId && message.status === 'unapproved');
|
.filter((message) => message.custodyId && message.status === 'unapproved');
|
||||||
|
|
||||||
if (custodianUnapprovedMessages && custodianUnapprovedMessages.length > 0) {
|
if (custodianUnapprovedMessages && custodianUnapprovedMessages.length > 0) {
|
||||||
return {
|
return {
|
||||||
...msgData,
|
...msgData,
|
||||||
custodyId: unapprovedTypedMessages[msgData.metamaskId]?.custodyId,
|
custodyId: unapprovedMessages[msgData.metamaskId]?.custodyId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
callBackgroundMethod,
|
callBackgroundMethod,
|
||||||
submitRequestToBackground,
|
submitRequestToBackground,
|
||||||
} from '../action-queue';
|
} from '../action-queue';
|
||||||
import { MetaMaskReduxState } from '../store';
|
import { MetaMaskReduxDispatch, MetaMaskReduxState } from '../store';
|
||||||
import { isErrorWithMessage } from '../../../shared/modules/error';
|
import { isErrorWithMessage } from '../../../shared/modules/error';
|
||||||
|
|
||||||
export function showInteractiveReplacementTokenBanner({
|
export function showInteractiveReplacementTokenBanner({
|
||||||
@ -21,7 +21,7 @@ export function showInteractiveReplacementTokenBanner({
|
|||||||
url: string;
|
url: string;
|
||||||
oldRefreshToken: string;
|
oldRefreshToken: string;
|
||||||
}): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
}): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||||
return async (dispatch) => {
|
return async (dispatch: MetaMaskReduxDispatch) => {
|
||||||
try {
|
try {
|
||||||
await submitRequestToBackground('showInteractiveReplacementTokenBanner', [
|
await submitRequestToBackground('showInteractiveReplacementTokenBanner', [
|
||||||
url,
|
url,
|
||||||
@ -37,7 +37,7 @@ export function showInteractiveReplacementTokenBanner({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function setTypedMessageInProgress(msgId: string) {
|
export function setTypedMessageInProgress(msgId: string) {
|
||||||
return async (dispatch: any) => {
|
return async (dispatch: MetaMaskReduxDispatch) => {
|
||||||
dispatch(showLoadingIndication());
|
dispatch(showLoadingIndication());
|
||||||
try {
|
try {
|
||||||
await submitRequestToBackground('setTypedMessageInProgress', [msgId]);
|
await submitRequestToBackground('setTypedMessageInProgress', [msgId]);
|
||||||
@ -51,6 +51,21 @@ export function setTypedMessageInProgress(msgId: string) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setPersonalMessageInProgress(msgId: string) {
|
||||||
|
return async (dispatch: MetaMaskReduxDispatch) => {
|
||||||
|
dispatch(showLoadingIndication());
|
||||||
|
try {
|
||||||
|
await submitRequestToBackground('setPersonalMessageInProgress', [msgId]);
|
||||||
|
} catch (error: any) {
|
||||||
|
log.error(error);
|
||||||
|
dispatch(displayWarning(error.message));
|
||||||
|
} finally {
|
||||||
|
await forceUpdateMetamaskState(dispatch);
|
||||||
|
dispatch(hideLoadingIndication());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory that contains all MMI actions ready to use
|
* A factory that contains all MMI actions ready to use
|
||||||
* Example usage:
|
* Example usage:
|
||||||
|
Loading…
Reference in New Issue
Block a user