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

Bump controllers v30.0.2 (#14906)

* bump @metamask/controllers to v30.0.2 and adapt
This commit is contained in:
Alex Donesky 2022-07-18 09:43:30 -05:00 committed by GitHub
parent 2744eaf760
commit 09164dcabb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 345 additions and 1511 deletions

View File

@ -358,12 +358,15 @@ function blockedDomainCheck() {
/**
* Redirects the current page to a phishing information page
*
* @param data
*/
function redirectToPhishingWarning() {
function redirectToPhishingWarning(data = {}) {
console.debug('MetaMask: Routing to Phishing Warning page.');
const baseUrl = process.env.PHISHING_WARNING_PAGE_URL;
window.location.href = `${baseUrl}#${querystring.stringify({
hostname: window.location.hostname,
href: window.location.href,
newIssueUrl: data.newIssueUrl,
})}`;
}

View File

@ -8,12 +8,19 @@ import {
TokenListController,
TokensController,
} from '@metamask/controllers';
import { MAINNET, ROPSTEN } from '../../../shared/constants/network';
import {
MAINNET,
MAINNET_NETWORK_ID,
ROPSTEN,
} from '../../../shared/constants/network';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
import DetectTokensController from './detect-tokens';
import NetworkController from './network';
import PreferencesController from './preferences';
const tokenIconsApiBaseUrl =
'https://static.metaswap.codefi.network/api/v1/tokenIcons';
describe('DetectTokensController', function () {
let tokenListController;
const sandbox = sinon.createSandbox();
@ -127,7 +134,6 @@ describe('DetectTokensController', function () {
});
tokenListController = new TokenListController({
chainId: '1',
useStaticTokenList: false,
onNetworkStateChange: sinon.spy(),
onPreferencesStateChange: sinon.spy(),
messenger: tokenListMessenger,
@ -179,7 +185,6 @@ describe('DetectTokensController', function () {
});
tokenListController = new TokenListController({
chainId: '3',
useStaticTokenList: false,
onNetworkStateChange: sinon.spy(),
onPreferencesStateChange: sinon.spy(),
messenger: tokenListMessengerRopsten,
@ -241,7 +246,7 @@ describe('DetectTokensController', function () {
),
);
await tokensController.removeAndIgnoreToken(tokenAddressToSkip);
await tokensController.ignoreTokens([tokenAddressToSkip]);
await controller.detectNewTokens();
assert.deepEqual(tokensController.state.tokens, [
@ -249,7 +254,8 @@ describe('DetectTokensController', function () {
address: toChecksumHexAddress(existingTokenAddress),
decimals: existingToken.decimals,
symbol: existingToken.symbol,
image: undefined,
aggregators: [],
image: `${tokenIconsApiBaseUrl}/${MAINNET_NETWORK_ID}/${existingTokenAddress}.png`,
isERC721: false,
},
]);
@ -303,14 +309,16 @@ describe('DetectTokensController', function () {
decimals: existingToken.decimals,
symbol: existingToken.symbol,
isERC721: false,
image: undefined,
aggregators: [],
image: `${tokenIconsApiBaseUrl}/${MAINNET_NETWORK_ID}/${existingTokenAddress}.png`,
},
{
address: toChecksumHexAddress(tokenAddressToAdd),
decimals: tokenToAdd.decimals,
symbol: tokenToAdd.symbol,
image: undefined,
isERC721: false,
aggregators: [],
image: `${tokenIconsApiBaseUrl}/${MAINNET_NETWORK_ID}/${tokenAddressToAdd}.png`,
},
]);
});
@ -363,15 +371,17 @@ describe('DetectTokensController', function () {
address: toChecksumHexAddress(existingTokenAddress),
decimals: existingToken.decimals,
symbol: existingToken.symbol,
image: undefined,
image: `${tokenIconsApiBaseUrl}/${MAINNET_NETWORK_ID}/${existingTokenAddress}.png`,
isERC721: false,
aggregators: [],
},
{
address: toChecksumHexAddress(tokenAddressToAdd),
decimals: tokenToAdd.decimals,
symbol: tokenToAdd.symbol,
image: undefined,
image: `${tokenIconsApiBaseUrl}/${MAINNET_NETWORK_ID}/${tokenAddressToAdd}.png`,
isERC721: false,
aggregators: [],
},
]);
});

View File

@ -54,9 +54,11 @@ import {
///: END:ONLY_INCLUDE_IN
import {
ASSET_TYPES,
TRANSACTION_STATUSES,
TRANSACTION_TYPES,
} from '../../shared/constants/transaction';
import { PHISHING_NEW_ISSUE_URLS } from '../../shared/constants/phishing';
import {
GAS_API_BASE_URL,
GAS_DEV_API_BASE_URL,
@ -85,7 +87,7 @@ import {
POLLING_TOKEN_ENVIRONMENT_TYPES,
SUBJECT_TYPES,
} from '../../shared/constants/app';
import { EVENT } from '../../shared/constants/metametrics';
import { EVENT, EVENT_NAMES } from '../../shared/constants/metametrics';
import { hexToDecimal } from '../../ui/helpers/utils/conversions.util';
import { getTokenValueParam } from '../../ui/helpers/utils/token-util';
@ -245,35 +247,28 @@ export default class MetamaskController extends EventEmitter {
config: { provider: this.provider },
state: initState.TokensController,
});
process.env.TOKEN_DETECTION_V2
? (this.assetsContractController = new AssetsContractController({
onPreferencesStateChange: (listener) =>
this.preferencesController.store.subscribe(listener),
onNetworkStateChange: (cb) =>
this.networkController.store.subscribe((networkState) => {
const modifiedNetworkState = {
...networkState,
provider: {
...networkState.provider,
chainId: hexToDecimal(networkState.provider.chainId),
},
};
return cb(modifiedNetworkState);
}),
config: {
provider: this.provider,
},
state: initState.AssetsContractController,
}))
: (this.assetsContractController = new AssetsContractController(
{
onPreferencesStateChange: (listener) =>
this.preferencesController.store.subscribe(listener),
},
{
provider: this.provider,
},
));
this.assetsContractController = new AssetsContractController(
{
onPreferencesStateChange: (listener) =>
this.preferencesController.store.subscribe(listener),
onNetworkStateChange: (cb) =>
this.networkController.store.subscribe((networkState) => {
const modifiedNetworkState = {
...networkState,
provider: {
...networkState.provider,
chainId: hexToDecimal(networkState.provider.chainId),
},
};
return cb(modifiedNetworkState);
}),
},
{
provider: this.provider,
},
initState.AssetsContractController,
);
this.collectiblesController = new CollectiblesController(
{
@ -301,6 +296,21 @@ export default class MetamaskController extends EventEmitter {
getERC1155TokenURI: this.assetsContractController.getERC1155TokenURI.bind(
this.assetsContractController,
),
onCollectibleAdded: ({ address, symbol, tokenId, standard, source }) =>
this.metaMetricsController.trackEvent({
event: EVENT_NAMES.NFT_ADDED,
category: EVENT.CATEGORIES.WALLET,
properties: {
token_contract_address: address,
token_symbol: symbol,
asset_type: ASSET_TYPES.COLLECTIBLE,
token_standard: standard,
source,
},
sensitiveProperties: {
tokenId,
},
}),
},
{},
initState.CollectiblesController,
@ -417,50 +427,23 @@ export default class MetamaskController extends EventEmitter {
const tokenListMessenger = this.controllerMessenger.getRestricted({
name: 'TokenListController',
});
process.env.TOKEN_DETECTION_V2
? (this.tokenListController = new TokenListController({
chainId: hexToDecimal(this.networkController.getCurrentChainId()),
onNetworkStateChange: (cb) =>
this.networkController.store.subscribe((networkState) => {
const modifiedNetworkState = {
...networkState,
provider: {
...networkState.provider,
chainId: hexToDecimal(networkState.provider.chainId),
},
};
return cb(modifiedNetworkState);
}),
messenger: tokenListMessenger,
state: initState.TokenListController,
}))
: (this.tokenListController = new TokenListController({
chainId: hexToDecimal(this.networkController.getCurrentChainId()),
useStaticTokenList: !this.preferencesController.store.getState()
.useTokenDetection,
onNetworkStateChange: (cb) =>
this.networkController.store.subscribe((networkState) => {
const modifiedNetworkState = {
...networkState,
provider: {
...networkState.provider,
chainId: hexToDecimal(networkState.provider.chainId),
},
};
return cb(modifiedNetworkState);
}),
onPreferencesStateChange: (cb) =>
this.preferencesController.store.subscribe((preferencesState) => {
const modifiedPreferencesState = {
...preferencesState,
useStaticTokenList: !this.preferencesController.store.getState()
.useTokenDetection,
};
return cb(modifiedPreferencesState);
}),
messenger: tokenListMessenger,
state: initState.TokenListController,
}));
this.tokenListController = new TokenListController({
chainId: hexToDecimal(this.networkController.getCurrentChainId()),
onNetworkStateChange: (cb) =>
this.networkController.store.subscribe((networkState) => {
const modifiedNetworkState = {
...networkState,
provider: {
...networkState.provider,
chainId: hexToDecimal(networkState.provider.chainId),
},
};
return cb(modifiedNetworkState);
}),
messenger: tokenListMessenger,
state: initState.TokenListController,
});
this.phishingController = new PhishingController();
@ -1586,7 +1569,6 @@ export default class MetamaskController extends EventEmitter {
tokensController,
),
updateTokenType: tokensController.updateTokenType.bind(tokensController),
removeToken: tokensController.removeAndIgnoreToken.bind(tokensController),
setAccountLabel: preferencesController.setAccountLabel.bind(
preferencesController,
),
@ -1960,20 +1942,14 @@ export default class MetamaskController extends EventEmitter {
: null,
/** Token Detection V2 */
addDetectedTokens: process.env.TOKEN_DETECTION_V2
? tokensController.addDetectedTokens.bind(tokensController)
: null,
importTokens: process.env.TOKEN_DETECTION_V2
? tokensController.importTokens.bind(tokensController)
: null,
ignoreTokens: process.env.TOKEN_DETECTION_V2
? tokensController.ignoreTokens.bind(tokensController)
: null,
getBalancesInSingleCall: process.env.TOKEN_DETECTION_V2
? assetsContractController.getBalancesInSingleCall.bind(
assetsContractController,
)
: null,
addDetectedTokens: tokensController.addDetectedTokens.bind(
tokensController,
),
addImportedTokens: tokensController.addTokens.bind(tokensController),
ignoreTokens: tokensController.ignoreTokens.bind(tokensController),
getBalancesInSingleCall: assetsContractController.getBalancesInSingleCall.bind(
assetsContractController,
),
};
}
@ -3342,9 +3318,13 @@ export default class MetamaskController extends EventEmitter {
if (sender.url) {
const { hostname } = new URL(sender.url);
// Check if new connection is blocked if phishing detection is on
if (usePhishDetect && this.phishingController.test(hostname)) {
log.debug('MetaMask - sending phishing warning for', hostname);
this.sendPhishingWarning(connectionStream, hostname);
const phishingTestResponse = this.phishingController.test(hostname);
if (usePhishDetect && phishingTestResponse?.result) {
this.sendPhishingWarning(
connectionStream,
hostname,
phishingTestResponse,
);
return;
}
}
@ -3422,11 +3402,15 @@ export default class MetamaskController extends EventEmitter {
* @param {*} connectionStream - The duplex stream to the per-page script,
* for sending the reload attempt to.
* @param {string} hostname - The hostname that triggered the suspicion.
* @param {object} phishingTestResponse - Result of calling `phishingController.test`,
* which is the result of calling eth-phishing-detects detector.check method https://github.com/MetaMask/eth-phishing-detect/blob/master/src/detector.js#L55-L112
*/
sendPhishingWarning(connectionStream, hostname) {
sendPhishingWarning(connectionStream, hostname, phishingTestResponse) {
const newIssueUrl = PHISHING_NEW_ISSUE_URLS[phishingTestResponse?.name];
const mux = setupMultiplex(connectionStream);
const phishingStream = mux.createStream('phishing');
phishingStream.write({ hostname });
phishingStream.write({ hostname, newIssueUrl });
}
/**

View File

@ -3217,147 +3217,13 @@
},
"@metamask/rpc-methods": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers": true,
"@metamask/controllers": true,
"@metamask/rpc-methods>@metamask/key-tree": true,
"@metamask/rpc-methods>@metamask/utils": true,
"@metamask/snap-controllers": true,
"eth-rpc-errors": true
}
},
"@metamask/rpc-methods>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry": true,
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/rpc-methods>@metamask/controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/rpc-methods>@metamask/key-tree": {
"packages": {
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": true,
@ -3418,148 +3284,14 @@
"setInterval": true
},
"packages": {
"@metamask/controllers": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/smart-transactions-controller>@metamask/controllers": true,
"@metamask/smart-transactions-controller>bignumber.js": true,
"@metamask/smart-transactions-controller>fast-json-patch": true,
"ethers": true,
"lodash": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry": true,
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/smart-transactions-controller>@metamask/controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>nanoid": {
"globals": {
"crypto.getRandomValues": true
@ -3595,11 +3327,11 @@
"setTimeout": true
},
"packages": {
"@metamask/controllers": true,
"@metamask/post-message-stream": true,
"@metamask/providers>@metamask/object-multiplex": true,
"@metamask/rpc-methods>@metamask/utils": true,
"@metamask/snap-controllers>@metamask/browser-passworder": true,
"@metamask/snap-controllers>@metamask/controllers": true,
"@metamask/snap-controllers>@metamask/execution-environments": true,
"@metamask/snap-controllers>@metamask/obs-store": true,
"@metamask/snap-controllers>ajv": true,
@ -3632,140 +3364,6 @@
"browserify>buffer": true
}
},
"@metamask/snap-controllers>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry": true,
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/snap-controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/snap-controllers>@metamask/obs-store": {
"packages": {
"@metamask/snap-controllers>@metamask/obs-store>through2": true,

View File

@ -3217,147 +3217,13 @@
},
"@metamask/rpc-methods": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers": true,
"@metamask/controllers": true,
"@metamask/rpc-methods>@metamask/key-tree": true,
"@metamask/rpc-methods>@metamask/utils": true,
"@metamask/snap-controllers": true,
"eth-rpc-errors": true
}
},
"@metamask/rpc-methods>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry": true,
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/rpc-methods>@metamask/controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/rpc-methods>@metamask/key-tree": {
"packages": {
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": true,
@ -3418,148 +3284,14 @@
"setInterval": true
},
"packages": {
"@metamask/controllers": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/smart-transactions-controller>@metamask/controllers": true,
"@metamask/smart-transactions-controller>bignumber.js": true,
"@metamask/smart-transactions-controller>fast-json-patch": true,
"ethers": true,
"lodash": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry": true,
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/smart-transactions-controller>@metamask/controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>nanoid": {
"globals": {
"crypto.getRandomValues": true
@ -3595,11 +3327,11 @@
"setTimeout": true
},
"packages": {
"@metamask/controllers": true,
"@metamask/post-message-stream": true,
"@metamask/providers>@metamask/object-multiplex": true,
"@metamask/rpc-methods>@metamask/utils": true,
"@metamask/snap-controllers>@metamask/browser-passworder": true,
"@metamask/snap-controllers>@metamask/controllers": true,
"@metamask/snap-controllers>@metamask/execution-environments": true,
"@metamask/snap-controllers>@metamask/obs-store": true,
"@metamask/snap-controllers>ajv": true,
@ -3632,140 +3364,6 @@
"browserify>buffer": true
}
},
"@metamask/snap-controllers>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry": true,
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/snap-controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/snap-controllers>@metamask/obs-store": {
"packages": {
"@metamask/snap-controllers>@metamask/obs-store>through2": true,

View File

@ -3217,147 +3217,13 @@
},
"@metamask/rpc-methods": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers": true,
"@metamask/controllers": true,
"@metamask/rpc-methods>@metamask/key-tree": true,
"@metamask/rpc-methods>@metamask/utils": true,
"@metamask/snap-controllers": true,
"eth-rpc-errors": true
}
},
"@metamask/rpc-methods>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry": true,
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/rpc-methods>@metamask/controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/rpc-methods>@metamask/key-tree": {
"packages": {
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": true,
@ -3418,148 +3284,14 @@
"setInterval": true
},
"packages": {
"@metamask/controllers": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/smart-transactions-controller>@metamask/controllers": true,
"@metamask/smart-transactions-controller>bignumber.js": true,
"@metamask/smart-transactions-controller>fast-json-patch": true,
"ethers": true,
"lodash": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry": true,
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/smart-transactions-controller>@metamask/controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>nanoid": {
"globals": {
"crypto.getRandomValues": true
@ -3595,11 +3327,11 @@
"setTimeout": true
},
"packages": {
"@metamask/controllers": true,
"@metamask/post-message-stream": true,
"@metamask/providers>@metamask/object-multiplex": true,
"@metamask/rpc-methods>@metamask/utils": true,
"@metamask/snap-controllers>@metamask/browser-passworder": true,
"@metamask/snap-controllers>@metamask/controllers": true,
"@metamask/snap-controllers>@metamask/execution-environments": true,
"@metamask/snap-controllers>@metamask/obs-store": true,
"@metamask/snap-controllers>ajv": true,
@ -3632,140 +3364,6 @@
"browserify>buffer": true
}
},
"@metamask/snap-controllers>@metamask/controllers": {
"globals": {
"Headers": true,
"URL": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.log": true,
"fetch": true,
"setInterval": true,
"setTimeout": true
},
"packages": {
"@ethereumjs/common": true,
"@ethereumjs/tx": true,
"@metamask/contract-metadata": true,
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>isomorphic-fetch": true,
"@metamask/controllers>multiformats": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry": true,
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/snap-controllers>nanoid": true,
"@storybook/api>fast-deep-equal": true,
"browserify>buffer": true,
"browserify>events": true,
"deep-freeze-strict": true,
"eth-ens-namehash": true,
"eth-json-rpc-infura": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
"ethereumjs-util": true,
"ethers": true,
"ethjs>ethjs-unit": true,
"immer": true,
"json-rpc-engine": true,
"jsonschema": true,
"punycode": true,
"single-call-balance-checker-abi": true,
"uuid": true,
"web3": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs": {
"globals": {
"clearInterval": true,
"setInterval": true
},
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-provider-http": true,
"ethjs>ethjs-unit": true,
"ethjs>ethjs-util": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"ethjs-query>babel-runtime": true,
"ethjs>ethjs-filter": true,
"ethjs>ethjs-util": true,
"promise-to-callback": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true,
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true,
"browserify>buffer": true,
"ethjs>number-to-bn": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": {
"globals": {
"console": true
},
"packages": {
"ethjs-query>babel-runtime": true,
"ethjs-query>ethjs-format": true,
"ethjs-query>ethjs-rpc": true,
"promise-to-callback": true
}
},
"@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": {
"packages": {
"browserify>process": true
}
},
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet": {
"packages": {
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet>uuid": true,
"@truffle/codec>utf8": true,
"browserify>buffer": true,
"browserify>crypto-browserify": true,
"ethereumjs-util": true,
"ethereumjs-util>ethereum-cryptography": true,
"ethereumjs-wallet>aes-js": true,
"ethereumjs-wallet>bs58check": true,
"ethereumjs-wallet>randombytes": true,
"ethers>@ethersproject/json-wallets>scrypt-js": true
}
},
"@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet>uuid": {
"globals": {
"crypto": true,
"msCrypto": true
}
},
"@metamask/snap-controllers>@metamask/obs-store": {
"packages": {
"@metamask/snap-controllers>@metamask/obs-store>through2": true,

View File

@ -117,7 +117,7 @@
"@keystonehq/metamask-airgapped-keyring": "0.2.1",
"@material-ui/core": "^4.11.0",
"@metamask/contract-metadata": "^1.31.0",
"@metamask/controllers": "^29.0.1",
"@metamask/controllers": "^30.0.2",
"@metamask/design-tokens": "^1.6.5",
"@metamask/eth-ledger-bridge-keyring": "^0.13.0",
"@metamask/eth-token-tracker": "^4.0.0",
@ -251,7 +251,7 @@
"@metamask/eslint-config-nodejs": "^9.0.0",
"@metamask/eslint-config-typescript": "^9.0.1",
"@metamask/forwarder": "^1.1.0",
"@metamask/phishing-warning": "^1.1.0",
"@metamask/phishing-warning": "^1.2.1",
"@metamask/test-dapp": "^5.1.1",
"@sentry/cli": "^1.58.0",
"@storybook/addon-a11y": "^6.3.12",

View File

@ -1,5 +1,5 @@
diff --git a/node_modules/abort-controller/browser.js b/node_modules/abort-controller/browser.js
index b0c5ec3..c8c8018 100644
index b0c5ec3..b61071b 100644
--- a/node_modules/abort-controller/browser.js
+++ b/node_modules/abort-controller/browser.js
@@ -2,12 +2,7 @@
@ -13,6 +13,7 @@ index b0c5ec3..c8c8018 100644
+const { AbortController } = globalThis;
/*eslint-enable @mysticatea/prettier */
module.exports = AbortController
-module.exports = AbortController
-module.exports.AbortSignal = AbortSignal
-module.exports.default = AbortController
+module.exports = { AbortController }

View File

@ -283,6 +283,7 @@ export const EVENT_NAMES = {
TOKEN_ADDED: 'Token Added',
TOKEN_DETECTED: 'Token Detected',
TOKEN_HIDDEN: 'Token Hidden',
NFT_ADDED: 'NFT Added',
TOKEN_IMPORT_CANCELED: 'Token Import Canceled',
TOKEN_IMPORT_CLICKED: 'Token Import Clicked',
};

View File

@ -0,0 +1,4 @@
export const PHISHING_NEW_ISSUE_URLS = {
MetaMask: 'https://github.com/metamask/eth-phishing-detect/issues/new',
PhishFort: 'https://github.com/phishfort/phishfort-lists/issues/new',
};

View File

@ -154,6 +154,26 @@ async function setupMocking(server, testSpecificMock) {
};
});
await server
.forGet(
'https://static.metaswap.codefi.network/api/v1/tokenIcons/1337/0x0d8775f648430679a709e98d2b0cb6250d2887ef.png',
)
.thenCallback(() => {
return {
statusCode: 200,
};
});
await server
.forGet(
'https://static.metaswap.codefi.network/api/v1/tokenIcons/1337/0x2efa2cb29c2341d8e5ba7d3262c9e9d6f1bf3711.png',
)
.thenCallback(() => {
return {
statusCode: 200,
};
});
testSpecificMock(server);
}

View File

@ -72,6 +72,9 @@ describe('Add existing token using search', function () {
fixtures: 'imported-account',
ganacheOptions,
title: this.test.title,
driverOptions: {
timeOut: 20000,
},
},
async ({ driver }) => {
await driver.navigate();
@ -80,7 +83,10 @@ describe('Add existing token using search', function () {
await driver.clickElement({ text: 'import tokens', tag: 'a' });
await driver.fill('#search-tokens', 'BAT');
await driver.clickElement({ text: 'BAT', tag: 'span' });
await driver.clickElement({
text: 'BAT',
tag: 'span',
});
await driver.clickElement({ text: 'Next', tag: 'button' });
await driver.clickElement({ text: 'Import Tokens', tag: 'button' });

View File

@ -1,6 +1,9 @@
const { strict: assert } = require('assert');
const { convertToHexValue, withFixtures } = require('../helpers');
const PHISHFORT_CDN_URL =
'https://cdn.jsdelivr.net/gh/phishfort/phishfort-lists@master/blacklists/hotlist.json';
describe('Phishing Detection', function () {
async function mockPhishingDetection(mockServer) {
await mockServer
@ -20,6 +23,14 @@ describe('Phishing Detection', function () {
};
});
}
async function mockPhishfortPhishingDetection(mockServer) {
await mockServer.forGet(PHISHFORT_CDN_URL).thenCallback(() => {
return {
statusCode: 200,
json: ['127.0.0.1'],
};
});
}
const ganacheOptions = {
accounts: [
{
@ -127,4 +138,27 @@ describe('Phishing Detection', function () {
},
);
});
it('should display the MetaMask Phishing Detection page with the correct new issue link if the issue was detected from the phishfort list', async function () {
await withFixtures(
{
fixtures: 'imported-account',
ganacheOptions,
title: this.test.title,
testSpecificMock: mockPhishfortPhishingDetection,
dapp: true,
failOnConsoleError: false,
},
async ({ driver }) => {
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
await driver.openNewPage('http://127.0.0.1:8080');
const newIssueLink = await driver.findElements(
"a[href='https://github.com/phishfort/phishfort-lists/issues/new?title=[Legitimate%20Site%20Blocked]%20127.0.0.1&body=http%3A%2F%2F127.0.0.1%3A8080%2F']",
);
assert.equal(newIssueLink.length, 1);
},
);
});
});

View File

@ -119,6 +119,16 @@ describe('Send ETH to a 40 character hexadecimal address', function () {
});
describe('Send ERC20 to a 40 character hexadecimal address', function () {
async function mockTstToken(server) {
await server
.forGet('https://token-api.metaswap.codefi.network/token/0x539')
.thenCallback(() => {
return {
statusCode: 200,
json: {},
};
});
}
const ganacheOptions = {
accounts: [
{
@ -137,7 +147,8 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () {
title: this.test.title,
failOnConsoleError: false,
},
async ({ driver }) => {
async ({ driver, mockServer }) => {
await mockTstToken(mockServer);
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
@ -236,7 +247,8 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () {
title: this.test.title,
failOnConsoleError: false,
},
async ({ driver }) => {
async ({ driver, mockServer }) => {
await mockTstToken(mockServer);
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);

View File

@ -18,6 +18,9 @@ describe('Swap Eth for another Token', function () {
ganacheOptions,
title: this.test.title,
failOnConsoleError: false,
driverOptions: {
timeOut: 20000,
},
},
async ({ driver }) => {
await driver.navigate();
@ -37,7 +40,6 @@ describe('Swap Eth for another Token', function () {
'[class="dropdown-search-list__closed-primary-label dropdown-search-list__select-default"]',
);
await driver.clickElement('[placeholder="Search for a token"]');
await driver.clickElement('[placeholder="Search for a token"]');
await driver.fill('[placeholder="Search for a token"]', 'DAI');
await driver.waitForSelector(
'[class="searchable-item-list__primary-label"]',

View File

@ -3,7 +3,7 @@ const Driver = require('./driver');
const ChromeDriver = require('./chrome');
const FirefoxDriver = require('./firefox');
async function buildWebDriver({ responsive, port } = {}) {
async function buildWebDriver({ responsive, port, timeOut } = {}) {
const browser = process.env.SELENIUM_BROWSER;
const {
@ -11,7 +11,7 @@ async function buildWebDriver({ responsive, port } = {}) {
extensionId,
extensionUrl,
} = await buildBrowserWebDriver(browser, { responsive, port });
const driver = new Driver(seleniumDriver, browser, extensionUrl);
const driver = new Driver(seleniumDriver, browser, extensionUrl, timeOut);
return {
driver,

View File

@ -56,8 +56,9 @@ export default function CollectiblesDetectionNotice() {
</Typography>
<Button
type="link"
onClick={() => {
history.push(EXPERIMENTAL_ROUTE);
onClick={(e) => {
e.preventDefault();
history.push(`${EXPERIMENTAL_ROUTE}#autodetect-nfts`);
}}
className="collectibles-detection-notice__message__link"
>

View File

@ -214,14 +214,16 @@ describe('Collectible Items', () => {
});
expect(screen.queryByText('New! NFT detection')).not.toBeInTheDocument();
});
it('should take user to the experimental settings tab in setings when user clicks "Turn on NFT detection in Settings"', () => {
it('should take user to the experimental settings tab in settings when user clicks "Turn on NFT detection in Settings"', () => {
render({
selectedAddress: ACCOUNT_2,
collectibles: COLLECTIBLES,
});
fireEvent.click(screen.queryByText('Turn on NFT detection in Settings'));
expect(historyPushMock).toHaveBeenCalledTimes(1);
expect(historyPushMock).toHaveBeenCalledWith(EXPERIMENTAL_ROUTE);
expect(historyPushMock).toHaveBeenCalledWith(
`${EXPERIMENTAL_ROUTE}#autodetect-nfts`,
);
});
it('should not render the Collectibles Detection Notice when currently selected network is Mainnet and currently selected account has no collectibles but use collectible autodetection preference is set to true', () => {
render({

View File

@ -4,7 +4,7 @@ import { useSelector, useDispatch } from 'react-redux';
import { chain } from 'lodash';
import {
importTokens,
addImportedTokens,
ignoreTokens,
setNewTokensImported,
} from '../../../store/actions';
@ -63,7 +63,7 @@ const DetectedToken = ({ setShowDetectedTokens }) => {
},
});
});
await dispatch(importTokens(selectedTokens));
await dispatch(addImportedTokens(selectedTokens));
const tokenSymbols = selectedTokens.map(({ symbol }) => symbol);
dispatch(setNewTokensImported(tokenSymbols.join(', ')));
};
@ -90,7 +90,15 @@ const DetectedToken = ({ setShowDetectedTokens }) => {
asset_type: ASSET_TYPES.TOKEN,
},
});
await dispatch(ignoreTokens(deSelectedTokens));
const deSelectedTokensAddresses = deSelectedTokens.map(
({ address }) => address,
);
await dispatch(
ignoreTokens({
tokensToIgnore: deSelectedTokensAddresses,
dontShowLoadingIndicator: true,
}),
);
setShowDetectedTokens(false);
};

View File

@ -12,7 +12,7 @@ import {
ASSET_ROUTE,
} from '../../../../helpers/constants/routes';
import { getCollectibles } from '../../../../ducks/metamask/metamask';
import { removeToken } from '../../../../store/actions';
import { ignoreTokens } from '../../../../store/actions';
import { isEqualCaseInsensitive } from '../../../../../shared/modules/string-utils';
const ConvertTokenToNFTModal = ({ hideModal, tokenAddress }) => {
@ -28,7 +28,12 @@ const ConvertTokenToNFTModal = ({ hideModal, tokenAddress }) => {
<Modal
onSubmit={async () => {
if (tokenAddedAsNFT) {
await dispatch(removeToken(tokenAddress));
await dispatch(
ignoreTokens({
tokensToIgnore: tokenAddress,
dontShowLoadingIndicator: true,
}),
);
const { tokenId } = tokenAddedAsNFT;
history.push({
pathname: `${ASSET_ROUTE}/${tokenAddress}/${tokenId}`,

View File

@ -17,7 +17,11 @@ function mapDispatchToProps(dispatch) {
return {
hideModal: () => dispatch(actions.hideModal()),
hideToken: (address) => {
dispatch(actions.removeToken(address)).then(() => {
dispatch(
actions.ignoreTokens({
tokensToIgnore: address,
}),
).then(() => {
dispatch(actions.hideModal());
});
},

View File

@ -15,7 +15,6 @@ export default class Jazzicon extends PureComponent {
className: PropTypes.string,
diameter: PropTypes.number,
style: PropTypes.object,
useTokenDetection: PropTypes.bool,
tokenList: PropTypes.object,
};
@ -48,13 +47,8 @@ export default class Jazzicon extends PureComponent {
}
appendJazzicon() {
const { address, diameter, useTokenDetection, tokenList } = this.props;
const image = iconFactory.iconForAddress(
address,
diameter,
useTokenDetection,
tokenList,
);
const { address, diameter, tokenList } = this.props;
const image = iconFactory.iconForAddress(address, diameter, tokenList);
this.container.current.appendChild(image);
}

View File

@ -89,7 +89,10 @@ import {
isValidHexAddress,
toChecksumHexAddress,
} from '../../../shared/modules/hexstring-utils';
import { sumHexes } from '../../helpers/utils/transactions.util';
import {
isSmartContractAddress,
sumHexes,
} from '../../helpers/utils/transactions.util';
import fetchEstimatedL1Fee from '../../helpers/utils/optimism/fetchEstimatedL1Fee';
import { TOKEN_STANDARDS, ETH } from '../../helpers/constants/common';
@ -1852,19 +1855,23 @@ export function updateRecipientUserInput(userInput) {
const inputIsValidHexAddress = isValidHexAddress(userInput);
let isProbablyAnAssetContract = false;
if (inputIsValidHexAddress) {
const { symbol, decimals } = getTokenMetadata(userInput, tokenMap) || {};
const smartContractAddress = await isSmartContractAddress(userInput);
if (smartContractAddress) {
const { symbol, decimals } =
getTokenMetadata(userInput, tokenMap) || {};
isProbablyAnAssetContract = symbol && decimals !== undefined;
isProbablyAnAssetContract = symbol && decimals !== undefined;
if (!isProbablyAnAssetContract) {
try {
const { standard } = await getTokenStandardAndDetails(
userInput,
sendingAddress,
);
isProbablyAnAssetContract = Boolean(standard);
} catch (e) {
console.log(e);
if (!isProbablyAnAssetContract) {
try {
const { standard } = await getTokenStandardAndDetails(
userInput,
sendingAddress,
);
isProbablyAnAssetContract = Boolean(standard);
} catch (e) {
console.log(e);
}
}
}
}
@ -1987,16 +1994,24 @@ export function updateSendAsset(
)),
};
await dispatch(hideLoadingIndication());
const balance = addHexPrefix(
calcTokenAmount(details.balance, details.decimals).toString(16),
);
const asset = {
type,
details,
balance,
error: null,
};
if (
if (details.standard === TOKEN_STANDARDS.ERC20) {
asset.balance = addHexPrefix(
calcTokenAmount(details.balance, details.decimals).toString(16),
);
await dispatch(
addHistoryEntry(
`sendFlow - user set asset to ERC20 token with symbol ${details.symbol} and address ${details.address}`,
),
);
} else if (
details.standard === TOKEN_STANDARDS.ERC1155 &&
type === ASSET_TYPES.COLLECTIBLE
) {
@ -2046,13 +2061,6 @@ export function updateSendAsset(
),
);
}
} else {
await dispatch(
addHistoryEntry(
`sendFlow - user set asset to ERC20 token with symbol ${details.symbol} and address ${details.address}`,
),
);
// do nothing extra.
}
await dispatch(actions.updateAsset(asset));

View File

@ -1,7 +1,4 @@
import {
isValidHexAddress,
toChecksumHexAddress,
} from '../../../shared/modules/hexstring-utils';
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
let iconFactory;
@ -17,29 +14,9 @@ function IconFactory(jazzicon) {
this.cache = {};
}
IconFactory.prototype.iconForAddress = function (
address,
diameter,
useTokenDetection,
tokenList,
) {
if (process.env.TOKEN_DETECTION_V2) {
if (iconExistsFor(address.toLowerCase(), tokenList)) {
return imageElFor(address.toLowerCase(), useTokenDetection, tokenList);
}
} else {
/** TODO: Remove during TOKEN_DETECTION_V2 feature flag clean up */
// When useTokenDetection flag is true the tokenList contains tokens with non-checksum address from the dynamic token service api,
// When useTokenDetection flag is false the tokenList contains tokens with checksum addresses from contract-metadata.
// So the flag indicates whether the address of tokens currently on the tokenList is checksum or not.
// And since the token.address from allTokens is checksumaddress
// tokenAddress have to be changed to lowercase when we are using dynamic list
const addr = useTokenDetection
? address.toLowerCase()
: toChecksumHexAddress(address);
if (iconExistsFor(addr, tokenList)) {
return imageElFor(addr, useTokenDetection, tokenList);
}
IconFactory.prototype.iconForAddress = function (address, diameter, tokenList) {
if (iconExistsFor(address.toLowerCase(), tokenList)) {
return imageElFor(address.toLowerCase(), tokenList);
}
return this.generateIdenticonSvg(address, diameter);
@ -74,16 +51,10 @@ function iconExistsFor(address, tokenList) {
);
}
function imageElFor(address, useTokenDetection, tokenList) {
function imageElFor(address, tokenList) {
const tokenMetadata = tokenList[address];
const fileName = tokenMetadata?.iconUrl;
// token from dynamic api list is fetched when useTokenDetection is true
// In the static list, the iconUrl will be holding only a filename for the image,
// the corresponding images will be available in the `images/contract/` location when the contract-metadata package was added to the extension
// so that it can be accessed using the filename in iconUrl.
const path = useTokenDetection ? fileName : `images/contract/${fileName}`;
const img = document.createElement('img');
img.src = process.env.TOKEN_DETECTION_V2 ? fileName : path;
img.src = tokenMetadata?.iconUrl;
img.style.width = '100%';
return img;
}

View File

@ -17,7 +17,7 @@ import PageContainer from '../../components/ui/page-container';
import {
addCollectibleVerifyOwnership,
getTokenStandardAndDetails,
removeToken,
ignoreTokens,
setNewCollectibleAddedMessage,
} from '../../store/actions';
import FormField from '../../components/ui/form-field';
@ -63,7 +63,10 @@ export default function AddCollectible() {
}
if (contractAddressToConvertFromTokenToCollectible) {
await dispatch(
removeToken(contractAddressToConvertFromTokenToCollectible),
ignoreTokens({
tokensToIgnore: contractAddressToConvertFromTokenToCollectible,
dontShowLoadingIndicator: true,
}),
);
}
dispatch(setNewCollectibleAddedMessage('success'));

View File

@ -14,7 +14,6 @@ export default class TokenList extends Component {
results: PropTypes.array,
selectedTokens: PropTypes.object,
onToggleToken: PropTypes.func,
useTokenDetection: PropTypes.bool,
};
render() {
@ -23,7 +22,6 @@ export default class TokenList extends Component {
selectedTokens = {},
onToggleToken,
tokens = [],
useTokenDetection,
} = this.props;
return results.length === 0 ? (
@ -38,14 +36,7 @@ export default class TokenList extends Component {
.fill(undefined)
.map((_, i) => {
const { iconUrl, symbol, name, address } = results[i] || {};
let iconPath = iconUrl;
if (!process.env.TOKEN_DETECTION_V2) {
/** TODO: Remove during TOKEN_DETECTION_V2 feature flag clean up */
// token from dynamic api list is fetched when useTokenDetection is true
iconPath = useTokenDetection
? iconUrl
: `images/contract/${iconUrl}`;
}
const iconPath = iconUrl;
const tokenAlreadyAdded = checkExistingAddresses(address, tokens);
const onClick = () =>
!tokenAlreadyAdded && onToggleToken(results[i]);

View File

@ -95,7 +95,7 @@ import {
import {
resetSwapsPostFetchState,
removeToken,
ignoreTokens,
setBackgroundSwapRouteState,
clearSwapsQuotes,
stopPollingForQuotes,
@ -359,7 +359,12 @@ export default function BuildQuote({
const onToSelect = useCallback(
(token) => {
if (destinationTokenAddedForSwap && token.address !== toAddress) {
dispatch(removeToken(toAddress));
dispatch(
ignoreTokens({
tokensToIgnore: toAddress,
dontShowLoadingIndicator: true,
}),
);
}
dispatch(setSwapToToken(token));
setVerificationClicked(false);

View File

@ -22,7 +22,7 @@ const createProps = (customProps = {}) => {
setBackgroundConnection({
resetPostFetchState: jest.fn(),
removeToken: jest.fn(),
ignoreTokens: jest.fn(),
setBackgroundSwapRouteState: jest.fn(),
clearSwapsQuotes: jest.fn(),
stopPollingForQuotes: jest.fn(),

View File

@ -76,7 +76,7 @@ import {
import {
resetBackgroundSwapsState,
setSwapsTokens,
removeToken,
ignoreTokens,
setBackgroundSwapRouteState,
setSwapsErrorKey,
} from '../../store/actions';
@ -214,7 +214,12 @@ export default function Swap() {
destinationTokenAddedForSwap &&
(!isAwaitingSwapRoute || conversionError)
) {
dispatch(removeToken(destinationTokenInfo?.address));
dispatch(
ignoreTokens({
tokensToIgnore: destinationTokenInfo?.address,
dontShowLoadingIndicator: true,
}),
);
}
};
}, [

View File

@ -2,7 +2,7 @@ import React, { useContext } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Redirect, useHistory, useParams } from 'react-router-dom';
import { getTokens } from '../../ducks/metamask/metamask';
import { getUseTokenDetection, getTokenList } from '../../selectors';
import { getTokenList } from '../../selectors';
import { useCopyToClipboard } from '../../hooks/useCopyToClipboard';
import Identicon from '../../components/ui/identicon';
import { I18nContext } from '../../contexts/i18n';
@ -32,7 +32,6 @@ export default function TokenDetailsPage() {
const t = useContext(I18nContext);
const tokens = useSelector(getTokens);
const tokenList = useSelector(getTokenList);
const useTokenDetection = useSelector(getUseTokenDetection);
const { address: tokenAddress } = useParams();
const tokenMetadata = Object.values(tokenList).find((token) =>
@ -40,10 +39,7 @@ export default function TokenDetailsPage() {
);
const aggregators = tokenMetadata?.aggregators?.join(', ');
const fileName = tokenMetadata?.iconUrl;
let imagePath = fileName;
if (!process.env.TOKEN_DETECTION_V2) {
imagePath = useTokenDetection ? fileName : `images/contract/${fileName}`;
}
const imagePath = fileName;
const token = tokens.find(({ address }) =>
isEqualCaseInsensitive(address, tokenAddress),

View File

@ -1654,10 +1654,10 @@ export function addDetectedTokens(newDetectedTokens) {
*
* @param tokensToImport
*/
export function importTokens(tokensToImport) {
export function addImportedTokens(tokensToImport) {
return async (dispatch) => {
try {
await promisifiedBackground.importTokens(tokensToImport);
await promisifiedBackground.addImportedTokens(tokensToImport);
} catch (error) {
log.error(error);
} finally {
@ -1667,18 +1667,32 @@ export function importTokens(tokensToImport) {
}
/**
* To add ignored tokens to state
* To add ignored token addresses to state
*
* @param tokensToIgnore
* @param options
* @param options.tokensToIgnore
* @param options.dontShowLoadingIndicator
*/
export function ignoreTokens(tokensToIgnore) {
export function ignoreTokens({
tokensToIgnore,
dontShowLoadingIndicator = false,
}) {
const _tokensToIgnore = Array.isArray(tokensToIgnore)
? tokensToIgnore
: [tokensToIgnore];
return async (dispatch) => {
if (!dontShowLoadingIndicator) {
dispatch(showLoadingIndication());
}
try {
await promisifiedBackground.ignoreTokens(tokensToIgnore);
await promisifiedBackground.ignoreTokens(_tokensToIgnore);
} catch (error) {
log.error(error);
dispatch(displayWarning(error.message));
} finally {
await forceUpdateMetamaskState(dispatch);
dispatch(hideLoadingIndication());
}
};
}
@ -1839,21 +1853,6 @@ export async function getTokenStandardAndDetails(
);
}
export function removeToken(address) {
return async (dispatch) => {
dispatch(showLoadingIndication());
try {
await promisifiedBackground.removeToken(address);
} catch (error) {
log.error(error);
dispatch(displayWarning(error.message));
} finally {
await forceUpdateMetamaskState(dispatch);
dispatch(hideLoadingIndication());
}
};
}
export function addTokens(tokens) {
return (dispatch) => {
if (Array.isArray(tokens)) {

View File

@ -1099,32 +1099,34 @@ describe('Actions', () => {
});
});
describe('#removeToken', () => {
describe('#ignoreTokens', () => {
afterEach(() => {
sinon.restore();
});
it('calls removeToken in background', async () => {
it('calls ignoreTokens in background', async () => {
const store = mockStore();
const removeTokenStub = sinon.stub().callsFake((_, cb) => cb());
const ignoreTokensStub = sinon.stub().callsFake((_, cb) => cb());
background.getApi.returns({
removeToken: removeTokenStub,
ignoreTokens: ignoreTokensStub,
getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)),
});
actions._setBackgroundConnection(background.getApi());
await store.dispatch(actions.removeToken());
expect(removeTokenStub.callCount).toStrictEqual(1);
await store.dispatch(
actions.ignoreTokens({ tokensToIgnore: '0x0000001' }),
);
expect(ignoreTokensStub.callCount).toStrictEqual(1);
});
it('should display warning when removeToken in background fails', async () => {
it('should display warning when ignoreTokens in background fails', async () => {
const store = mockStore();
background.getApi.returns({
removeToken: sinon.stub().callsFake((_, cb) => cb(new Error('error'))),
ignoreTokens: sinon.stub().callsFake((_, cb) => cb(new Error('error'))),
getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)),
});
@ -1140,7 +1142,9 @@ describe('Actions', () => {
{ type: 'HIDE_LOADING_INDICATION' },
];
await store.dispatch(actions.removeToken());
await store.dispatch(
actions.ignoreTokens({ tokensToIgnore: '0x0000001' }),
);
expect(store.getActions()).toStrictEqual(expectedActions);
});

View File

@ -2807,56 +2807,15 @@
resolved "https://registry.yarnpkg.com/@metamask/browser-passworder/-/browser-passworder-3.0.0.tgz#c06744e66a968ffa13f70cc71a7d3b15d86b0ee7"
integrity sha512-hD10mgvhcDkZX8wnauw8udp1K2MzcbZfrN7Yon9sQ+OqVK9kiQ4VhZAyZNZTy9KJLtfoVD9Y2F6L4gEese7hDA==
"@metamask/contract-metadata@^1.31.0", "@metamask/contract-metadata@^1.33.0", "@metamask/contract-metadata@^1.35.0":
"@metamask/contract-metadata@^1.31.0", "@metamask/contract-metadata@^1.35.0":
version "1.35.0"
resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.35.0.tgz#2bf2b8f2b6fdbd5132f0bcfa594b6c02dc71c42e"
integrity sha512-zfZKwLFOVrQS8vTFoeoNCG9JhqmK4oyembGiGVVpUAYD9BHVZnd9WpicGoUC07ROXLEyQuAK9AJZNBtqwwzfEQ==
"@metamask/controllers@^29.0.1":
version "29.0.1"
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-29.0.1.tgz#8b6d066a23877c82de005ce566b7fd6bbaa7cc13"
integrity sha512-jOZiaOg9E0Th2Pq75kRNMtKmku7dba6KVvKA5olEd7YB+2tzCkBh+TU16RAS1RUQzGXahWvt+kXDV/FLFa2ixg==
dependencies:
"@ethereumjs/common" "^2.3.1"
"@ethereumjs/tx" "^3.2.1"
"@keystonehq/metamask-airgapped-keyring" "^0.3.0"
"@metamask/contract-metadata" "^1.33.0"
"@metamask/metamask-eth-abis" "3.0.0"
"@metamask/types" "^1.1.0"
"@types/uuid" "^8.3.0"
abort-controller "^3.0.0"
async-mutex "^0.2.6"
babel-runtime "^6.26.0"
deep-freeze-strict "^1.1.1"
eth-ens-namehash "^2.0.8"
eth-json-rpc-infura "^5.1.0"
eth-keyring-controller "^7.0.2"
eth-method-registry "1.1.0"
eth-phishing-detect "^1.1.16"
eth-query "^2.1.2"
eth-rpc-errors "^4.0.0"
eth-sig-util "^3.0.0"
ethereumjs-util "^7.0.10"
ethereumjs-wallet "^1.0.1"
ethers "^5.4.1"
ethjs-unit "^0.1.6"
fast-deep-equal "^3.1.3"
immer "^9.0.6"
isomorphic-fetch "^3.0.0"
json-rpc-engine "^6.1.0"
jsonschema "^1.2.4"
multiformats "^9.5.2"
nanoid "^3.1.31"
punycode "^2.1.1"
single-call-balance-checker-abi "^1.0.0"
uuid "^8.3.2"
web3 "^0.20.7"
web3-provider-engine "^16.0.3"
"@metamask/controllers@^30.0.0":
version "30.0.1"
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-30.0.1.tgz#8d57d6abcb9bf0376c00b5bcc79154096f115c16"
integrity sha512-uOAjReSEofaX54g9tUauCzPDK1pE4iGLj12oPSoV6LDUpHPOO5H0PnERg+qNK6fWBXf7sFOTFNsx2n2WYQgt3g==
"@metamask/controllers@^30.0.0", "@metamask/controllers@^30.0.2":
version "30.0.2"
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-30.0.2.tgz#0a5512598d2997e34d3542889cae7088fe1fa4b8"
integrity sha512-nIUQaaGPzy9whcAvzwHCRsMtw3YWdBv6mUiN9EA2CKdYUesnVj4bpXSSMEso1oEhsNRa2/XTZSb6i+Odo/raJw==
dependencies:
"@ethereumjs/common" "^2.3.1"
"@ethereumjs/tx" "^3.2.1"
@ -3052,13 +3011,13 @@
"@metamask/safe-event-emitter" "^2.0.0"
through2 "^2.0.3"
"@metamask/phishing-warning@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@metamask/phishing-warning/-/phishing-warning-1.1.0.tgz#0d5764327c413dd1900db786e295bd729530ca66"
integrity sha512-39N7lU9fdkXZKHn/hbkiEhv1oJ3mabPjYMk22582a7XzdBD5wgxDf5qHsXXQlOq+uI3lBU9VVKD7K7Z2lcgapw==
"@metamask/phishing-warning@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@metamask/phishing-warning/-/phishing-warning-1.2.1.tgz#75554f8653a32c8d101c5b315707dd7990daf156"
integrity sha512-VfQLwiQmXg9YrJzBmDKN6eknNEkxYEAssTpoObVrDYiS91LjuDU59IjoIc1SN9IzDNxIP6ZI95dOculsm/o4qw==
dependencies:
"@metamask/design-tokens" "^1.6.0"
"@metamask/post-message-stream" "^4.0.0"
"@metamask/post-message-stream" "^5.1.0"
globalthis "1.0.1"
obj-multiplex "^1.0.0"
pump "^3.0.0"
@ -3071,6 +3030,14 @@
dependencies:
readable-stream "2.3.3"
"@metamask/post-message-stream@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@metamask/post-message-stream/-/post-message-stream-5.1.0.tgz#3e9a2ed11b540b3868a0a28ffa8ec5a6e5fca29d"
integrity sha512-BQi/H67iM7wdtmvoPfgW9bazk/WjvRhXRa5lQ1FpgDlASv1bsCDJaQQ83Q3BwYyisnpnjgJRuC/2bRmas0LMxA==
dependencies:
"@metamask/utils" "^2.0.0"
readable-stream "2.3.3"
"@metamask/providers@^9.0.0":
version "9.0.0"
resolved "https://registry.yarnpkg.com/@metamask/providers/-/providers-9.0.0.tgz#644684f9eceb952138e80afb9103c7e39d8350fe"
@ -11173,7 +11140,7 @@ eth-method-registry@^2.0.0:
dependencies:
ethjs "^0.4.0"
eth-phishing-detect@^1.1.16, eth-phishing-detect@^1.2.0:
eth-phishing-detect@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/eth-phishing-detect/-/eth-phishing-detect-1.2.0.tgz#11b357776b2d1b98a9ac594a1343e5184fc26bf0"
integrity sha512-+M7D4dhu5tkSA9b5eiBwDeJCjwy+7Lv49nuTEw8fNZIZUAVZC3d2XHatBq1MOW7J8kxNGbBdgBuIf65opI7Tkg==