1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 01:47:00 +01:00

Adding browser outdated notification (#17027)

* Adding browser outdated notification

* updating dependency

* adding unit tests for util function

* adding unit tests for selectors, lintfix

* Added Tests, refactored notification delay logic

* lint:fix

* adding test coverage for method parameter

* Update app/scripts/controllers/app-state.js

adding documentation details

Co-authored-by: Mark Stacey <markjstacey@gmail.com>

* moving declaration into test

* Update app/scripts/controllers/app-state.test.js

spacing in test file

Co-authored-by: Mark Stacey <markjstacey@gmail.com>

* Update jest.config.js

removing duplicate entries

Co-authored-by: Mark Stacey <markjstacey@gmail.com>

* using async submitRequestToBackground method

* removing unused import

* removing unnecessary link syntax in notification

* adding opera and edge and associated tests

* handling the undefined case in bowser.satisfies

* setOutdatedBrowserWarningLastShown try/catch

* lint:fix

* Removing try/catch and letting errors bubble up

Removing deprecated displayWarning method

Co-authored-by: Mark Stacey <markjstacey@gmail.com>

* taking out forceMetamaskUpdateState call

* excludint app-state test from mocha test suite

* Added note: Jest files should match Mocha excluded

* syntax error, lint:fix

---------

Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
vthomas13 2023-02-02 13:56:41 -05:00 committed by GitHub
parent aededb1c71
commit 532a10f9f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 222 additions and 1 deletions

View File

@ -235,6 +235,7 @@ module.exports = {
'test/e2e/**/*.spec.js', 'test/e2e/**/*.spec.js',
], ],
excludedFiles: [ excludedFiles: [
'app/scripts/controllers/app-state.test.js',
'app/scripts/controllers/network/**/*.test.js', 'app/scripts/controllers/network/**/*.test.js',
'app/scripts/controllers/permissions/**/*.test.js', 'app/scripts/controllers/permissions/**/*.test.js',
'app/scripts/lib/**/*.test.js', 'app/scripts/lib/**/*.test.js',
@ -257,11 +258,12 @@ module.exports = {
* Jest tests * Jest tests
* *
* These are files that make use of globals and syntax introduced by the * These are files that make use of globals and syntax introduced by the
* Jest library. * Jest library. The files in this section should match the Mocha excludedFiles section.
*/ */
{ {
files: [ files: [
'**/__snapshots__/*.snap', '**/__snapshots__/*.snap',
'app/scripts/controllers/app-state.test.js',
'app/scripts/controllers/network/**/*.test.js', 'app/scripts/controllers/network/**/*.test.js',
'app/scripts/controllers/network/provider-api-tests/*.js', 'app/scripts/controllers/network/provider-api-tests/*.js',
'app/scripts/controllers/permissions/**/*.test.js', 'app/scripts/controllers/permissions/**/*.test.js',

View File

@ -5,6 +5,7 @@ module.exports = {
'./app/scripts/lib/**/*.test.js', './app/scripts/lib/**/*.test.js',
'./app/scripts/migrations/*.test.js', './app/scripts/migrations/*.test.js',
'./app/scripts/platforms/*.test.js', './app/scripts/platforms/*.test.js',
'./app/scripts/controllers/app-state.test.js',
'./app/scripts/controllers/network/**/*.test.js', './app/scripts/controllers/network/**/*.test.js',
'./app/scripts/controllers/permissions/**/*.test.js', './app/scripts/controllers/permissions/**/*.test.js',
'./app/scripts/constants/error-utils.test.js', './app/scripts/constants/error-utils.test.js',

View File

@ -2602,6 +2602,9 @@
"message": "other snaps", "message": "other snaps",
"description": "Used in the 'permission_rpc' message." "description": "Used in the 'permission_rpc' message."
}, },
"outdatedBrowserNotification": {
"message": "Your browser is out of date. If you don't update your browser, you won't be able to get security patches and new features from MetaMask."
},
"padlock": { "padlock": {
"message": "Padlock" "message": "Padlock"
}, },

View File

@ -37,6 +37,8 @@ export default class AppStateController extends EventEmitter {
fullScreenGasPollTokens: [], fullScreenGasPollTokens: [],
recoveryPhraseReminderHasBeenShown: false, recoveryPhraseReminderHasBeenShown: false,
recoveryPhraseReminderLastShown: new Date().getTime(), recoveryPhraseReminderLastShown: new Date().getTime(),
outdatedBrowserWarningLastShown: new Date().getTime(),
collectiblesDetectionNoticeDismissed: false,
showTestnetMessageInDropdown: true, showTestnetMessageInDropdown: true,
showPortfolioTooltip: true, showPortfolioTooltip: true,
showBetaHeader: isBeta(), showBetaHeader: isBeta(),
@ -161,6 +163,17 @@ export default class AppStateController extends EventEmitter {
}); });
} }
/**
* Record the timestamp of the last time the user has seen the outdated browser warning
*
* @param {number} lastShown - Timestamp (in milliseconds) of when the user was last shown the warning.
*/
setOutdatedBrowserWarningLastShown(lastShown) {
this.store.updateState({
outdatedBrowserWarningLastShown: lastShown,
});
}
/** /**
* Sets the last active time to the current time. * Sets the last active time to the current time.
*/ */

View File

@ -0,0 +1,33 @@
import AppStateController from './app-state';
describe('AppStateController', () => {
describe('setOutdatedBrowserWarningLastShown', () => {
it('should set the last shown time', () => {
const appStateController = new AppStateController({
addUnlockListener: jest.fn(),
isUnlocked: jest.fn(() => true),
initState: {},
onInactiveTimeout: jest.fn(),
showUnlockRequest: jest.fn(),
preferencesStore: {
subscribe: jest.fn(),
getState: jest.fn(() => ({
preferences: {
autoLockTimeLimit: 0,
},
})),
},
qrHardwareStore: {
subscribe: jest.fn(),
},
});
const date = new Date();
appStateController.setOutdatedBrowserWarningLastShown(date);
expect(
appStateController.store.getState().outdatedBrowserWarningLastShown,
).toStrictEqual(date);
});
});
});

View File

@ -1878,6 +1878,10 @@ export default class MetamaskController extends EventEmitter {
appStateController.setRecoveryPhraseReminderLastShown.bind( appStateController.setRecoveryPhraseReminderLastShown.bind(
appStateController, appStateController,
), ),
setOutdatedBrowserWarningLastShown:
appStateController.setOutdatedBrowserWarningLastShown.bind(
appStateController,
),
setShowTestnetMessageInDropdown: setShowTestnetMessageInDropdown:
appStateController.setShowTestnetMessageInDropdown.bind( appStateController.setShowTestnetMessageInDropdown.bind(
appStateController, appStateController,

View File

@ -35,6 +35,7 @@ module.exports = {
setupFilesAfterEnv: ['<rootDir>/test/jest/setup.js'], setupFilesAfterEnv: ['<rootDir>/test/jest/setup.js'],
testMatch: [ testMatch: [
'<rootDir>/app/scripts/constants/error-utils.test.js', '<rootDir>/app/scripts/constants/error-utils.test.js',
'<rootDir>/app/scripts/controllers/app-state.test.js',
'<rootDir>/app/scripts/controllers/network/**/*.test.js', '<rootDir>/app/scripts/controllers/network/**/*.test.js',
'<rootDir>/app/scripts/controllers/permissions/**/*.test.js', '<rootDir>/app/scripts/controllers/permissions/**/*.test.js',
'<rootDir>/app/scripts/flask/**/*.test.js', '<rootDir>/app/scripts/flask/**/*.test.js',

View File

@ -2106,6 +2106,11 @@
"browserify>browser-resolve": true "browserify>browser-resolve": true
} }
}, },
"bowser": {
"globals": {
"define": true
}
},
"browserify>assert": { "browserify>assert": {
"globals": { "globals": {
"Buffer": true "Buffer": true

View File

@ -2430,6 +2430,11 @@
"browserify>browser-resolve": true "browserify>browser-resolve": true
} }
}, },
"bowser": {
"globals": {
"define": true
}
},
"browserify>assert": { "browserify>assert": {
"globals": { "globals": {
"Buffer": true "Buffer": true

View File

@ -2106,6 +2106,11 @@
"browserify>browser-resolve": true "browserify>browser-resolve": true
} }
}, },
"bowser": {
"globals": {
"define": true
}
},
"browserify>assert": { "browserify>assert": {
"globals": { "globals": {
"Buffer": true "Buffer": true

View File

@ -269,6 +269,7 @@
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"bignumber.js": "^4.1.0", "bignumber.js": "^4.1.0",
"bn.js": "^4.11.7", "bn.js": "^4.11.7",
"bowser": "^2.11.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"copy-to-clipboard": "^3.0.8", "copy-to-clipboard": "^3.0.8",
"currency-formatter": "^1.4.2", "currency-formatter": "^1.4.2",

View File

@ -13,3 +13,9 @@ _supportRequestLink =
export const SUPPORT_REQUEST_LINK = _supportRequestLink; export const SUPPORT_REQUEST_LINK = _supportRequestLink;
export const CONTRACT_ADDRESS_LINK = _contractAddressLink; export const CONTRACT_ADDRESS_LINK = _contractAddressLink;
export const PASSWORD_MIN_LENGTH = 8; export const PASSWORD_MIN_LENGTH = 8;
export const OUTDATED_BROWSER_VERSIONS = {
chrome: '<80',
edge: '<80',
firefox: '<78',
opera: '<67',
};

View File

@ -5,6 +5,7 @@ import * as ethUtil from 'ethereumjs-util';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { getFormattedIpfsUrl } from '@metamask/assets-controllers'; import { getFormattedIpfsUrl } from '@metamask/assets-controllers';
import slip44 from '@metamask/slip44'; import slip44 from '@metamask/slip44';
import bowser from 'bowser';
import { CHAIN_IDS } from '../../../shared/constants/network'; import { CHAIN_IDS } from '../../../shared/constants/network';
import { import {
toChecksumHexAddress, toChecksumHexAddress,
@ -16,6 +17,7 @@ import {
TRUNCATED_ADDRESS_END_CHARS, TRUNCATED_ADDRESS_END_CHARS,
} from '../../../shared/constants/labels'; } from '../../../shared/constants/labels';
import { Numeric } from '../../../shared/modules/Numeric'; import { Numeric } from '../../../shared/modules/Numeric';
import { OUTDATED_BROWSER_VERSIONS } from '../constants/common';
// formatData :: ( date: <Unix Timestamp> ) -> String // formatData :: ( date: <Unix Timestamp> ) -> String
export function formatDate(date, format = "M/d/y 'at' T") { export function formatDate(date, format = "M/d/y 'at' T") {
@ -328,6 +330,12 @@ export function getURL(url) {
} }
} }
export function getIsBrowserDeprecated(
browser = bowser.getParser(window.navigator.userAgent),
) {
return browser.satisfies(OUTDATED_BROWSER_VERSIONS) ?? false;
}
export function getURLHost(url) { export function getURLHost(url) {
return getURL(url)?.host || ''; return getURL(url)?.host || '';
} }

View File

@ -1,3 +1,4 @@
import Bowser from 'bowser';
import { BN } from 'ethereumjs-util'; import { BN } from 'ethereumjs-util';
import { addHexPrefixToObjectValues } from '../../../shared/lib/swaps-utils'; import { addHexPrefixToObjectValues } from '../../../shared/lib/swaps-utils';
import { toPrecisionWithoutTrailingZeros } from '../../../shared/lib/transactions-controller-utils'; import { toPrecisionWithoutTrailingZeros } from '../../../shared/lib/transactions-controller-utils';
@ -194,6 +195,77 @@ describe('util', () => {
}); });
}); });
describe('#getIsBrowserDeprecated', () => {
it('should call Bowser.getParser when no parameter is passed', () => {
const spy = jest.spyOn(Bowser, 'getParser');
util.getIsBrowserDeprecated();
expect(spy).toHaveBeenCalled();
});
it('should return false when given a modern chrome browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.2623.112 Safari/537.36',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(false);
});
it('should return true when given an outdated chrome browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.2623.112 Safari/537.36',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(true);
});
it('should return false when given a modern firefox browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(false);
});
it('should return true when given an outdated firefox browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(true);
});
it('should return false when given a modern opera browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.3578.98 Safari/537.36 OPR/68.0.3135.47',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(false);
});
it('should return true when given an outdated opera browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 OPR/58.0.3135.47',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(true);
});
it('should return false when given a modern edge browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.3578.98 Safari/537.36 Edg/81.0.416.68',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(false);
});
it('should return true when given an outdated edge browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 Edge/71.0.416.68',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(true);
});
it('should return false when given an unknown browser', () => {
const browser = Bowser.getParser(
'Mozilla/5.0 (Nintendo Switch; WebApplet) AppleWebKit/609.4 (KHTML, like Gecko) NF/6.0.2.21.3 NintendoBrowser/5.1.0.22474',
);
const result = util.getIsBrowserDeprecated(browser);
expect(result).toStrictEqual(false);
});
});
describe('normalizing values', function () { describe('normalizing values', function () {
describe('#getRandomFileName', () => { describe('#getRandomFileName', () => {
it('should only return a string containing alphanumeric characters', () => { it('should only return a string containing alphanumeric characters', () => {

View File

@ -122,6 +122,8 @@ export default class Home extends PureComponent {
showRecoveryPhraseReminder: PropTypes.bool.isRequired, showRecoveryPhraseReminder: PropTypes.bool.isRequired,
setRecoveryPhraseReminderHasBeenShown: PropTypes.func.isRequired, setRecoveryPhraseReminderHasBeenShown: PropTypes.func.isRequired,
setRecoveryPhraseReminderLastShown: PropTypes.func.isRequired, setRecoveryPhraseReminderLastShown: PropTypes.func.isRequired,
showOutdatedBrowserWarning: PropTypes.bool.isRequired,
setOutdatedBrowserWarningLastShown: PropTypes.func.isRequired,
seedPhraseBackedUp: (props) => { seedPhraseBackedUp: (props) => {
if ( if (
props.seedPhraseBackedUp !== null && props.seedPhraseBackedUp !== null &&
@ -249,6 +251,11 @@ export default class Home extends PureComponent {
setRecoveryPhraseReminderLastShown(new Date().getTime()); setRecoveryPhraseReminderLastShown(new Date().getTime());
}; };
onOutdatedBrowserWarningClose = () => {
const { setOutdatedBrowserWarningLastShown } = this.props;
setOutdatedBrowserWarningLastShown(new Date().getTime());
};
renderNotifications() { renderNotifications() {
const { t } = this.context; const { t } = this.context;
const { const {
@ -265,6 +272,7 @@ export default class Home extends PureComponent {
shouldShowErrors, shouldShowErrors,
///: END:ONLY_INCLUDE_IN ///: END:ONLY_INCLUDE_IN
infuraBlocked, infuraBlocked,
showOutdatedBrowserWarning,
newNetworkAdded, newNetworkAdded,
setNewNetworkAdded, setNewNetworkAdded,
newCollectibleAddedMessage, newCollectibleAddedMessage,
@ -490,6 +498,14 @@ export default class Home extends PureComponent {
key="home-infuraBlockedNotification" key="home-infuraBlockedNotification"
/> />
) : null} ) : null}
{showOutdatedBrowserWarning ? (
<HomeNotification
descriptionText={t('outdatedBrowserNotification')}
acceptText={t('gotIt')}
onAccept={this.onOutdatedBrowserWarningClose}
key="home-outdatedBrowserNotification"
/>
) : null}
{Object.keys(newCustomNetworkAdded).length !== 0 && ( {Object.keys(newCustomNetworkAdded).length !== 0 && (
<Popover className="home__new-network-added"> <Popover className="home__new-network-added">
<i className="fa fa-check-circle fa-2x home__new-network-added__check-circle" /> <i className="fa fa-check-circle fa-2x home__new-network-added__check-circle" />

View File

@ -17,6 +17,7 @@ import {
getShowWhatsNewPopup, getShowWhatsNewPopup,
getSortedAnnouncementsToShow, getSortedAnnouncementsToShow,
getShowRecoveryPhraseReminder, getShowRecoveryPhraseReminder,
getShowOutdatedBrowserWarning,
getNewNetworkAdded, getNewNetworkAdded,
hasUnsignedQRHardwareTransaction, hasUnsignedQRHardwareTransaction,
hasUnsignedQRHardwareMessage, hasUnsignedQRHardwareMessage,
@ -36,6 +37,7 @@ import {
setAlertEnabledness, setAlertEnabledness,
setRecoveryPhraseReminderHasBeenShown, setRecoveryPhraseReminderHasBeenShown,
setRecoveryPhraseReminderLastShown, setRecoveryPhraseReminderLastShown,
setOutdatedBrowserWarningLastShown,
setNewNetworkAdded, setNewNetworkAdded,
setNewCollectibleAddedMessage, setNewCollectibleAddedMessage,
setRemoveCollectibleMessage, setRemoveCollectibleMessage,
@ -54,6 +56,7 @@ import {
import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask'; import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask';
import { getSwapsFeatureIsLive } from '../../ducks/swaps/swaps'; import { getSwapsFeatureIsLive } from '../../ducks/swaps/swaps';
import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { getEnvironmentType } from '../../../app/scripts/lib/util';
import { getIsBrowserDeprecated } from '../../helpers/utils/util';
import { import {
ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_NOTIFICATION,
ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_POPUP,
@ -143,6 +146,8 @@ const mapStateToProps = (state) => {
portfolioTooltipWasShownInThisSession: portfolioTooltipWasShownInThisSession:
getPortfolioTooltipWasShownInThisSession(state), getPortfolioTooltipWasShownInThisSession(state),
showRecoveryPhraseReminder: getShowRecoveryPhraseReminder(state), showRecoveryPhraseReminder: getShowRecoveryPhraseReminder(state),
showOutdatedBrowserWarning:
getIsBrowserDeprecated() && getShowOutdatedBrowserWarning(state),
seedPhraseBackedUp, seedPhraseBackedUp,
newNetworkAdded: getNewNetworkAdded(state), newNetworkAdded: getNewNetworkAdded(state),
isSigningQRHardwareTransaction, isSigningQRHardwareTransaction,
@ -172,6 +177,9 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(setRecoveryPhraseReminderHasBeenShown()), dispatch(setRecoveryPhraseReminderHasBeenShown()),
setRecoveryPhraseReminderLastShown: (lastShown) => setRecoveryPhraseReminderLastShown: (lastShown) =>
dispatch(setRecoveryPhraseReminderLastShown(lastShown)), dispatch(setRecoveryPhraseReminderLastShown(lastShown)),
setOutdatedBrowserWarningLastShown: (lastShown) => {
dispatch(setOutdatedBrowserWarningLastShown(lastShown));
},
setNewNetworkAdded: (newNetwork) => { setNewNetworkAdded: (newNetwork) => {
console.log({ newNetwork }); console.log({ newNetwork });
dispatch(setNewNetworkAdded(newNetwork)); dispatch(setNewNetworkAdded(newNetwork));

View File

@ -1066,6 +1066,15 @@ export function getShowRecoveryPhraseReminder(state) {
return currentTime - recoveryPhraseReminderLastShown >= frequency; return currentTime - recoveryPhraseReminderLastShown >= frequency;
} }
export function getShowOutdatedBrowserWarning(state) {
const { outdatedBrowserWarningLastShown } = state.metamask;
if (!outdatedBrowserWarningLastShown) {
return true;
}
const currentTime = new Date().getTime();
return currentTime - outdatedBrowserWarningLastShown >= DAY * 2;
}
export function getShowPortfolioTooltip(state) { export function getShowPortfolioTooltip(state) {
return state.metamask.showPortfolioTooltip; return state.metamask.showPortfolioTooltip;
} }

View File

@ -269,6 +269,26 @@ describe('Selectors', () => {
expect(useCurrencyRateCheck).toStrictEqual(true); expect(useCurrencyRateCheck).toStrictEqual(true);
}); });
it('#getShowOutdatedBrowserWarning returns false if outdatedBrowserWarningLastShown is less than 2 days ago', () => {
mockState.metamask.showOutdatedBrowserWarning = true;
const timestamp = new Date();
timestamp.setDate(timestamp.getDate() - 1);
mockState.metamask.outdatedBrowserWarningLastShown = timestamp.getTime();
const showOutdatedBrowserWarning =
selectors.getShowOutdatedBrowserWarning(mockState);
expect(showOutdatedBrowserWarning).toStrictEqual(false);
});
it('#getShowOutdatedBrowserWarning returns true if outdatedBrowserWarningLastShown is more than 2 days ago', () => {
mockState.metamask.showOutdatedBrowserWarning = true;
const timestamp = new Date();
timestamp.setDate(timestamp.getDate() - 3);
mockState.metamask.outdatedBrowserWarningLastShown = timestamp.getTime();
const showOutdatedBrowserWarning =
selectors.getShowOutdatedBrowserWarning(mockState);
expect(showOutdatedBrowserWarning).toStrictEqual(true);
});
it('#getTotalUnapprovedSignatureRequestCount', () => { it('#getTotalUnapprovedSignatureRequestCount', () => {
const totalUnapprovedSignatureRequestCount = const totalUnapprovedSignatureRequestCount =
selectors.getTotalUnapprovedSignatureRequestCount(mockState); selectors.getTotalUnapprovedSignatureRequestCount(mockState);

View File

@ -3274,6 +3274,14 @@ export function setRecoveryPhraseReminderLastShown(lastShown) {
}; };
} }
export function setOutdatedBrowserWarningLastShown(lastShown) {
return async () => {
await submitRequestToBackground('setOutdatedBrowserWarningLastShown', [
lastShown,
]);
};
}
export function loadingMethodDataStarted() { export function loadingMethodDataStarted() {
return { return {
type: actionConstants.LOADING_METHOD_DATA_STARTED, type: actionConstants.LOADING_METHOD_DATA_STARTED,

View File

@ -24147,6 +24147,7 @@ __metadata:
bify-module-groups: ^2.0.0 bify-module-groups: ^2.0.0
bignumber.js: ^4.1.0 bignumber.js: ^4.1.0
bn.js: ^4.11.7 bn.js: ^4.11.7
bowser: ^2.11.0
brfs: ^2.0.2 brfs: ^2.0.2
browser-util-inspect: ^0.2.0 browser-util-inspect: ^0.2.0
browserify: ^16.5.1 browserify: ^16.5.1