Merge remote-tracking branch 'origin/master' into Version-v10.7.0

feature/default_network_editable
ryanml 3 years ago
commit 4d94261deb
  1. 2
      .circleci/scripts/yarn-audit.sh
  2. 11
      CHANGELOG.md
  3. 12
      app/scripts/controllers/metametrics.js
  4. 28
      app/scripts/controllers/swaps.js
  5. 17
      app/scripts/controllers/swaps.test.js
  6. 10
      app/scripts/first-time-state.js
  7. 2
      app/scripts/metamask-controller.js
  8. 5
      package.json
  9. 5
      test/e2e/tests/custom-rpc-history.spec.js
  10. 38
      ui/components/app/dropdowns/network-dropdown.js
  11. 2
      ui/components/app/dropdowns/network-dropdown.test.js
  12. 12
      ui/pages/settings/networks-tab/networks-tab.constants.js
  13. 22
      yarn.lock

@ -5,7 +5,7 @@ set -o pipefail
# use `improved-yarn-audit` since that allows for exclude # use `improved-yarn-audit` since that allows for exclude
# exclude 1002401 until we remove use of 3Box, 1002581 until we can find a better solution # exclude 1002401 until we remove use of 3Box, 1002581 until we can find a better solution
yarn run improved-yarn-audit --ignore-dev-deps --min-severity moderate --exclude 1002401,1002581 yarn run improved-yarn-audit --ignore-dev-deps --min-severity moderate --exclude 1002401,1002581,GHSA-93q8-gq69-wqmw,GHSA-257v-vj4p-3w2h
audit_status="$?" audit_status="$?"
# Use a bitmask to ignore INFO and LOW severity audit results # Use a bitmask to ignore INFO and LOW severity audit results

@ -23,6 +23,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#12727](https://github.com/MetaMask/metamask-extension/pull/12727): Make toggle buttons keyboard accessible - [#12727](https://github.com/MetaMask/metamask-extension/pull/12727): Make toggle buttons keyboard accessible
- [#12729](https://github.com/MetaMask/metamask-extension/pull/12729): Swaps: Fix issue with wrapping and unwrapping when an address contains uppercase characters - [#12729](https://github.com/MetaMask/metamask-extension/pull/12729): Swaps: Fix issue with wrapping and unwrapping when an address contains uppercase characters
- [#12631](https://github.com/MetaMask/metamask-extension/pull/12631): Fix bug preventing sending high precision decimal amounts of tokens in the send flow - [#12631](https://github.com/MetaMask/metamask-extension/pull/12631): Fix bug preventing sending high precision decimal amounts of tokens in the send flow
## [10.6.2]
### Fixed
- [#12770](https://github.com/MetaMask/metamask-extension/pull/12770): Fixed display of best quote in swaps quotes modal
- [#12786](https://github.com/MetaMask/metamask-extension/pull/12786): Ensure there is a single localhost option in network selector and that it is clickable
## [10.6.1]
### Fixed
- [#12573](https://github.com/MetaMask/metamask-extension/pull/12573): Ensure metrics api errors do not impact user experience
## [10.6.0] ## [10.6.0]
### Added ### Added
@ -2614,6 +2622,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.7.0...HEAD [Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.7.0...HEAD
[10.7.0]: https://github.com/MetaMask/metamask-extension/compare/v10.6.0...v10.7.0 [10.7.0]: https://github.com/MetaMask/metamask-extension/compare/v10.6.0...v10.7.0
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.6.2...HEAD
[10.6.2]: https://github.com/MetaMask/metamask-extension/compare/v10.6.1...v10.6.2
[10.6.1]: https://github.com/MetaMask/metamask-extension/compare/v10.6.0...v10.6.1
[10.6.0]: https://github.com/MetaMask/metamask-extension/compare/v10.5.2...v10.6.0 [10.6.0]: https://github.com/MetaMask/metamask-extension/compare/v10.5.2...v10.6.0
[10.5.2]: https://github.com/MetaMask/metamask-extension/compare/v10.5.1...v10.5.2 [10.5.2]: https://github.com/MetaMask/metamask-extension/compare/v10.5.1...v10.5.2
[10.5.1]: https://github.com/MetaMask/metamask-extension/compare/v10.5.0...v10.5.1 [10.5.1]: https://github.com/MetaMask/metamask-extension/compare/v10.5.0...v10.5.1

@ -15,6 +15,10 @@ const defaultCaptureException = (err) => {
}); });
}; };
const exceptionsToFilter = {
[`You must pass either an "anonymousId" or a "userId".`]: true,
};
/** /**
* @typedef {import('../../../shared/constants/metametrics').MetaMetricsContext} MetaMetricsContext * @typedef {import('../../../shared/constants/metametrics').MetaMetricsContext} MetaMetricsContext
* @typedef {import('../../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload * @typedef {import('../../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload
@ -61,7 +65,13 @@ export default class MetaMetricsController {
initState, initState,
captureException = defaultCaptureException, captureException = defaultCaptureException,
}) { }) {
this._captureException = captureException; this._captureException = (err) => {
// This is a temporary measure. Currently there are errors flooding sentry due to a problem in how we are tracking anonymousId
// We intend on removing this as soon as we understand how to correctly solve that problem.
if (!exceptionsToFilter[err.message]) {
captureException(err);
}
};
const prefState = preferencesStore.getState(); const prefState = preferencesStore.getState();
this.chainId = getCurrentChainId(); this.chainId = getCurrentChainId();
this.network = getNetworkIdentifier(); this.network = getNetworkIdentifier();

@ -28,6 +28,7 @@ import {
} from '../../../ui/pages/swaps/swaps.util'; } from '../../../ui/pages/swaps/swaps.util';
import fetchWithCache from '../../../ui/helpers/utils/fetch-with-cache'; import fetchWithCache from '../../../ui/helpers/utils/fetch-with-cache';
import { MINUTE, SECOND } from '../../../shared/constants/time'; import { MINUTE, SECOND } from '../../../shared/constants/time';
import { isEqualCaseInsensitive } from '../../../ui/helpers/utils/util';
import { NETWORK_EVENTS } from './network'; import { NETWORK_EVENTS } from './network';
// The MAX_GAS_LIMIT is a number that is higher than the maximum gas costs we have observed on any aggregator // The MAX_GAS_LIMIT is a number that is higher than the maximum gas costs we have observed on any aggregator
@ -91,7 +92,7 @@ export default class SwapsController {
networkController, networkController,
provider, provider,
getProviderConfig, getProviderConfig,
tokenRatesStore, getTokenRatesState,
fetchTradesInfo = defaultFetchTradesInfo, fetchTradesInfo = defaultFetchTradesInfo,
getCurrentChainId, getCurrentChainId,
getEIP1559GasFeeEstimates, getEIP1559GasFeeEstimates,
@ -105,7 +106,7 @@ export default class SwapsController {
this._getEIP1559GasFeeEstimates = getEIP1559GasFeeEstimates; this._getEIP1559GasFeeEstimates = getEIP1559GasFeeEstimates;
this.getBufferedGasLimit = getBufferedGasLimit; this.getBufferedGasLimit = getBufferedGasLimit;
this.tokenRatesStore = tokenRatesStore; this.getTokenRatesState = getTokenRatesState;
this.pollCount = 0; this.pollCount = 0;
this.getProviderConfig = getProviderConfig; this.getProviderConfig = getProviderConfig;
@ -610,7 +611,9 @@ export default class SwapsController {
} }
async _findTopQuoteAndCalculateSavings(quotes = {}) { async _findTopQuoteAndCalculateSavings(quotes = {}) {
const tokenConversionRates = this.tokenRatesStore.contractExchangeRates; const {
contractExchangeRates: tokenConversionRates,
} = this.getTokenRatesState();
const { const {
swapsState: { customGasPrice, customMaxPriorityFeePerGas }, swapsState: { customGasPrice, customMaxPriorityFeePerGas },
} = this.store.getState(); } = this.store.getState();
@ -734,7 +737,12 @@ export default class SwapsController {
decimalAdjustedDestinationAmount, decimalAdjustedDestinationAmount,
); );
const tokenConversionRate = tokenConversionRates[destinationToken]; const tokenConversionRate =
tokenConversionRates[
Object.keys(tokenConversionRates).find((tokenAddress) =>
isEqualCaseInsensitive(tokenAddress, destinationToken),
)
];
const conversionRateForSorting = tokenConversionRate || 1; const conversionRateForSorting = tokenConversionRate || 1;
const ethValueOfTokens = decimalAdjustedDestinationAmount.times( const ethValueOfTokens = decimalAdjustedDestinationAmount.times(
@ -777,7 +785,17 @@ export default class SwapsController {
isSwapsDefaultTokenAddress( isSwapsDefaultTokenAddress(
newQuotes[topAggId].destinationToken, newQuotes[topAggId].destinationToken,
chainId, chainId,
) || Boolean(tokenConversionRates[newQuotes[topAggId]?.destinationToken]); ) ||
Boolean(
tokenConversionRates[
Object.keys(tokenConversionRates).find((tokenAddress) =>
isEqualCaseInsensitive(
tokenAddress,
newQuotes[topAggId]?.destinationToken,
),
)
],
);
let savings = null; let savings = null;

@ -82,12 +82,12 @@ const MOCK_FETCH_METADATA = {
chainId: MAINNET_CHAIN_ID, chainId: MAINNET_CHAIN_ID,
}; };
const MOCK_TOKEN_RATES_STORE = { const MOCK_TOKEN_RATES_STORE = () => ({
contractExchangeRates: { contractExchangeRates: {
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': 2, '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': 2,
'0x1111111111111111111111111111111111111111': 0.1, '0x1111111111111111111111111111111111111111': 0.1,
}, },
}; });
const MOCK_GET_PROVIDER_CONFIG = () => ({ type: 'FAKE_NETWORK' }); const MOCK_GET_PROVIDER_CONFIG = () => ({ type: 'FAKE_NETWORK' });
@ -161,7 +161,7 @@ describe('SwapsController', function () {
networkController: getMockNetworkController(), networkController: getMockNetworkController(),
provider, provider,
getProviderConfig: MOCK_GET_PROVIDER_CONFIG, getProviderConfig: MOCK_GET_PROVIDER_CONFIG,
tokenRatesStore: MOCK_TOKEN_RATES_STORE, getTokenRatesState: MOCK_TOKEN_RATES_STORE,
fetchTradesInfo: fetchTradesInfoStub, fetchTradesInfo: fetchTradesInfoStub,
getCurrentChainId: getCurrentChainIdStub, getCurrentChainId: getCurrentChainIdStub,
getEIP1559GasFeeEstimates: getEIP1559GasFeeEstimatesStub, getEIP1559GasFeeEstimates: getEIP1559GasFeeEstimatesStub,
@ -211,7 +211,7 @@ describe('SwapsController', function () {
networkController, networkController,
provider, provider,
getProviderConfig: MOCK_GET_PROVIDER_CONFIG, getProviderConfig: MOCK_GET_PROVIDER_CONFIG,
tokenRatesStore: MOCK_TOKEN_RATES_STORE, getTokenRatesState: MOCK_TOKEN_RATES_STORE,
fetchTradesInfo: fetchTradesInfoStub, fetchTradesInfo: fetchTradesInfoStub,
getCurrentChainId: getCurrentChainIdStub, getCurrentChainId: getCurrentChainIdStub,
}); });
@ -235,7 +235,7 @@ describe('SwapsController', function () {
networkController, networkController,
provider, provider,
getProviderConfig: MOCK_GET_PROVIDER_CONFIG, getProviderConfig: MOCK_GET_PROVIDER_CONFIG,
tokenRatesStore: MOCK_TOKEN_RATES_STORE, getTokenRatesState: MOCK_TOKEN_RATES_STORE,
fetchTradesInfo: fetchTradesInfoStub, fetchTradesInfo: fetchTradesInfoStub,
getCurrentChainId: getCurrentChainIdStub, getCurrentChainId: getCurrentChainIdStub,
}); });
@ -259,7 +259,7 @@ describe('SwapsController', function () {
networkController, networkController,
provider, provider,
getProviderConfig: MOCK_GET_PROVIDER_CONFIG, getProviderConfig: MOCK_GET_PROVIDER_CONFIG,
tokenRatesStore: MOCK_TOKEN_RATES_STORE, getTokenRatesState: MOCK_TOKEN_RATES_STORE,
fetchTradesInfo: fetchTradesInfoStub, fetchTradesInfo: fetchTradesInfoStub,
getCurrentChainId: getCurrentChainIdStub, getCurrentChainId: getCurrentChainIdStub,
}); });
@ -816,9 +816,10 @@ describe('SwapsController', function () {
.stub(swapsController, '_getERC20Allowance') .stub(swapsController, '_getERC20Allowance')
.resolves(ethers.BigNumber.from(1)); .resolves(ethers.BigNumber.from(1));
swapsController.tokenRatesStore = { swapsController.getTokenRatesState = () => ({
contractExchangeRates: {}, contractExchangeRates: {},
}; });
const [newQuotes, topAggId] = await swapsController.fetchAndSetQuotes( const [newQuotes, topAggId] = await swapsController.fetchAndSetQuotes(
MOCK_FETCH_PARAMS, MOCK_FETCH_PARAMS,
MOCK_FETCH_METADATA, MOCK_FETCH_METADATA,

@ -10,7 +10,15 @@
const initialState = { const initialState = {
config: {}, config: {},
PreferencesController: { PreferencesController: {
frequentRpcListDetail: [], frequentRpcListDetail: [
{
rpcUrl: 'http://localhost:8545',
chainId: '0x539',
ticker: 'ETH',
nickname: 'Localhost 8545',
rpcPrefs: {},
},
],
}, },
}; };

@ -564,7 +564,7 @@ export default class MetamaskController extends EventEmitter {
getProviderConfig: this.networkController.getProviderConfig.bind( getProviderConfig: this.networkController.getProviderConfig.bind(
this.networkController, this.networkController,
), ),
tokenRatesStore: this.tokenRatesController.state, getTokenRatesState: () => this.tokenRatesController.state,
getCurrentChainId: this.networkController.getCurrentChainId.bind( getCurrentChainId: this.networkController.getCurrentChainId.bind(
this.networkController, this.networkController,
), ),

@ -93,7 +93,8 @@
"netmask": "^2.0.1", "netmask": "^2.0.1",
"pubnub/superagent-proxy": "^3.0.0", "pubnub/superagent-proxy": "^3.0.0",
"pull-ws": "^3.3.2", "pull-ws": "^3.3.2",
"ws": "^7.4.6" "ws": "^7.4.6",
"json-schema": "^0.4.0"
}, },
"dependencies": { "dependencies": {
"3box": "^1.10.2", "3box": "^1.10.2",
@ -294,7 +295,7 @@
"gulp-watch": "^5.0.1", "gulp-watch": "^5.0.1",
"gulp-zip": "^4.0.0", "gulp-zip": "^4.0.0",
"history": "^5.0.0", "history": "^5.0.0",
"improved-yarn-audit": "^2.3.3", "improved-yarn-audit": "^3.0.0",
"jest": "^26.6.3", "jest": "^26.6.3",
"jsdom": "^11.2.0", "jsdom": "^11.2.0",
"koa": "^2.7.0", "koa": "^2.7.0",

@ -84,7 +84,7 @@ describe('Stores custom RPC history', function () {
await rpcUrlInput.clear(); await rpcUrlInput.clear();
await rpcUrlInput.sendKeys(duplicateRpcUrl); await rpcUrlInput.sendKeys(duplicateRpcUrl);
await driver.findElement({ await driver.findElement({
text: 'This URL is currently used by the localhost network.', text: 'This URL is currently used by the Localhost 8545 network.',
tag: 'h6', tag: 'h6',
}); });
}, },
@ -123,7 +123,8 @@ describe('Stores custom RPC history', function () {
await chainIdInput.clear(); await chainIdInput.clear();
await chainIdInput.sendKeys(duplicateChainId); await chainIdInput.sendKeys(duplicateChainId);
await driver.findElement({ await driver.findElement({
text: 'This Chain ID is currently used by the localhost network.', text:
'This Chain ID is currently used by the Localhost 8545 network.',
tag: 'h6', tag: 'h6',
}); });
}, },

@ -7,7 +7,10 @@ import classnames from 'classnames';
import Button from '../../ui/button'; import Button from '../../ui/button';
import * as actions from '../../../store/actions'; import * as actions from '../../../store/actions';
import { openAlert as displayInvalidCustomNetworkAlert } from '../../../ducks/alerts/invalid-custom-network'; import { openAlert as displayInvalidCustomNetworkAlert } from '../../../ducks/alerts/invalid-custom-network';
import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'; import {
NETWORK_TYPE_RPC,
LOCALHOST_RPC_URL,
} from '../../../../shared/constants/network';
import { isPrefixedFormattedHexString } from '../../../../shared/modules/network.utils'; import { isPrefixedFormattedHexString } from '../../../../shared/modules/network.utils';
import ColorIndicator from '../../ui/color-indicator'; import ColorIndicator from '../../ui/color-indicator';
@ -68,7 +71,7 @@ function mapDispatchToProps(dispatch) {
}), }),
); );
}, },
hideTestNetMessage: () => dispatch(actions.hideTestNetMessage()), hideTestNetMessage: () => actions.hideTestNetMessage(),
}; };
} }
@ -149,7 +152,7 @@ class NetworkDropdown extends Component {
); );
} }
renderCustomRpcList(rpcListDetail, provider) { renderCustomRpcList(rpcListDetail, provider, opts = {}) {
const reversedRpcListDetail = rpcListDetail.slice().reverse(); const reversedRpcListDetail = rpcListDetail.slice().reverse();
return reversedRpcListDetail.map((entry) => { return reversedRpcListDetail.map((entry) => {
@ -157,6 +160,14 @@ class NetworkDropdown extends Component {
const isCurrentRpcTarget = const isCurrentRpcTarget =
provider.type === NETWORK_TYPE_RPC && rpcUrl === provider.rpcUrl; provider.type === NETWORK_TYPE_RPC && rpcUrl === provider.rpcUrl;
let borderColor = COLORS.UI2;
if (isCurrentRpcTarget) {
borderColor = COLORS.WHITE;
}
if (opts.isLocalHost) {
borderColor = 'localhost';
}
return ( return (
<DropdownMenuItem <DropdownMenuItem
key={`common${rpcUrl}`} key={`common${rpcUrl}`}
@ -180,10 +191,10 @@ class NetworkDropdown extends Component {
<div className="network-check__transparent"></div> <div className="network-check__transparent"></div>
)} )}
<ColorIndicator <ColorIndicator
color={COLORS.UI2} color={opts.isLocalHost ? 'localhost' : COLORS.UI2}
size={SIZES.LG} size={SIZES.LG}
type={ColorIndicator.TYPES.FILLED} type={ColorIndicator.TYPES.FILLED}
borderColor={isCurrentRpcTarget ? COLORS.WHITE : COLORS.UI2} borderColor={borderColor}
/> />
<span <span
className="network-name-item" className="network-name-item"
@ -278,6 +289,12 @@ class NetworkDropdown extends Component {
hideTestNetMessage, hideTestNetMessage,
} = this.props; } = this.props;
const rpcListDetail = this.props.frequentRpcListDetail; const rpcListDetail = this.props.frequentRpcListDetail;
const rpcListDetailWithoutLocalHost = rpcListDetail.filter(
(rpc) => rpc.rpcUrl !== LOCALHOST_RPC_URL,
);
const rpcListDetailForLocalHost = rpcListDetail.filter(
(rpc) => rpc.rpcUrl === LOCALHOST_RPC_URL,
);
const isOpen = this.props.networkDropdownOpen; const isOpen = this.props.networkDropdownOpen;
const { t } = this.context; const { t } = this.context;
@ -340,7 +357,10 @@ class NetworkDropdown extends Component {
<div className="network-dropdown-list"> <div className="network-dropdown-list">
{this.renderNetworkEntry('mainnet')} {this.renderNetworkEntry('mainnet')}
{this.renderCustomRpcList(rpcListDetail, this.props.provider)} {this.renderCustomRpcList(
rpcListDetailWithoutLocalHost,
this.props.provider,
)}
<div <div
className={classnames('network-dropdown-testnets', { className={classnames('network-dropdown-testnets', {
@ -351,7 +371,11 @@ class NetworkDropdown extends Component {
{this.renderNetworkEntry('kovan')} {this.renderNetworkEntry('kovan')}
{this.renderNetworkEntry('rinkeby')} {this.renderNetworkEntry('rinkeby')}
{this.renderNetworkEntry('goerli')} {this.renderNetworkEntry('goerli')}
{this.renderNetworkEntry('localhost')} {this.renderCustomRpcList(
rpcListDetailForLocalHost,
this.props.provider,
{ isLocalHost: true },
)}
</div> </div>
</div> </div>

@ -4,6 +4,7 @@ import thunk from 'redux-thunk';
import Button from '../../ui/button'; import Button from '../../ui/button';
import { mountWithRouter } from '../../../../test/lib/render-helpers'; import { mountWithRouter } from '../../../../test/lib/render-helpers';
import ColorIndicator from '../../ui/color-indicator'; import ColorIndicator from '../../ui/color-indicator';
import { LOCALHOST_RPC_URL } from '../../../../shared/constants/network';
import NetworkDropdown from './network-dropdown'; import NetworkDropdown from './network-dropdown';
import { DropdownMenuItem } from './dropdown'; import { DropdownMenuItem } from './dropdown';
@ -55,6 +56,7 @@ describe('Network Dropdown', () => {
frequentRpcListDetail: [ frequentRpcListDetail: [
{ chainId: '0x1a', rpcUrl: 'http://localhost:7545' }, { chainId: '0x1a', rpcUrl: 'http://localhost:7545' },
{ rpcUrl: 'http://localhost:7546' }, { rpcUrl: 'http://localhost:7546' },
{ rpcUrl: LOCALHOST_RPC_URL, nickname: 'localhost' },
], ],
}, },
appState: { appState: {

@ -5,9 +5,6 @@ import {
KOVAN, KOVAN,
KOVAN_CHAIN_ID, KOVAN_CHAIN_ID,
KOVAN_RPC_URL, KOVAN_RPC_URL,
LOCALHOST,
LOCALHOST_CHAIN_ID,
LOCALHOST_RPC_URL,
MAINNET, MAINNET,
MAINNET_CHAIN_ID, MAINNET_CHAIN_ID,
MAINNET_RPC_URL, MAINNET_RPC_URL,
@ -65,15 +62,6 @@ const defaultNetworksData = [
ticker: 'ETH', ticker: 'ETH',
blockExplorerUrl: 'https://kovan.etherscan.io', blockExplorerUrl: 'https://kovan.etherscan.io',
}, },
{
labelKey: LOCALHOST,
iconColor: '#29B6AF',
providerType: LOCALHOST,
rpcUrl: LOCALHOST_RPC_URL,
chainId: LOCALHOST_CHAIN_ID,
ticker: 'ETH',
blockExplorerUrl: '',
},
]; ];
export { defaultNetworksData }; export { defaultNetworksData };

@ -6825,9 +6825,9 @@ ansi-regex@^4.1.0:
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
ansi-regex@^5.0.0: ansi-regex@^5.0.0:
version "5.0.0" version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^2.2.1: ansi-styles@^2.2.1:
version "2.2.1" version "2.2.1"
@ -16580,10 +16580,10 @@ import-local@^3.0.2:
pkg-dir "^4.2.0" pkg-dir "^4.2.0"
resolve-cwd "^3.0.0" resolve-cwd "^3.0.0"
improved-yarn-audit@^2.3.3: improved-yarn-audit@^3.0.0:
version "2.3.3" version "3.0.0"
resolved "https://registry.yarnpkg.com/improved-yarn-audit/-/improved-yarn-audit-2.3.3.tgz#da0be78be4b678c73733066c9ccd21e1958fae8c" resolved "https://registry.yarnpkg.com/improved-yarn-audit/-/improved-yarn-audit-3.0.0.tgz#dfb09cea1a3a92c790ea2b4056431f6fb1b99bfa"
integrity sha512-chZ7zPKGsA+CZeMExNPf9WZhETJLkC+u8cQlkQC9XyPZqQPctn3FavefTjXBXmX3Azin8WcoAbaok1FvjkLf6A== integrity sha512-b7CrBYYwMidtPciCBkW62C7vqGjAV10bxcAWHeJvGrltrcMSEnG5I9CQgi14nmAlUKUQiSvpz47Lo3d7Z3Vjcg==
imurmurhash@^0.1.4: imurmurhash@^0.1.4:
version "0.1.4" version "0.1.4"
@ -18901,10 +18901,10 @@ json-schema-traverse@^1.0.0:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
json-schema@0.2.3: json-schema@0.2.3, json-schema@^0.4.0:
version "0.2.3" version "0.4.0"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
json-stable-stringify-without-jsonify@^1.0.1: json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1" version "1.0.1"

Loading…
Cancel
Save