Skip to content

Commit 83216da

Browse files
authored
Merge branch 'develop' into feat/use-infura-gas-api
2 parents 770076b + 985b652 commit 83216da

File tree

186 files changed

+2235
-1148
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

186 files changed

+2235
-1148
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
diff --git a/dist/Standards/NftStandards/ERC721/ERC721Standard.js b/dist/Standards/NftStandards/ERC721/ERC721Standard.js
2+
index d9286b0c0e607d2857f3ee7dad40d13a6c11d7d7..4e12e4b590b1f34a66602d63035f1905917f8c93 100644
3+
--- a/dist/Standards/NftStandards/ERC721/ERC721Standard.js
4+
+++ b/dist/Standards/NftStandards/ERC721/ERC721Standard.js
5+
@@ -66,7 +66,10 @@ class ERC721Standard {
6+
const contract = new contracts_1.Contract(address, metamask_eth_abis_1.abiERC721, this.provider);
7+
const supportsMetadata = yield this.contractSupportsMetadataInterface(address);
8+
if (!supportsMetadata) {
9+
- throw new Error('Contract does not support ERC721 metadata interface.');
10+
+ // Do not throw error here, supporting Metadata interface is optional even though majority of ERC721 nfts do support it.
11+
+ // This change is made because of instances of NFTs that are ERC404( mixed ERC20 / ERC721 implementation).
12+
+ // As of today, ERC404 is unofficial but some people use it, the contract does not support Metadata interface, but it has the tokenURI() fct.
13+
+ console.error('Contract does not support ERC721 metadata interface.');
14+
}
15+
return contract.tokenURI(tokenId);
16+
});

app/_locales/en/messages.json

Lines changed: 12 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/images/scroll.svg

Lines changed: 25 additions & 0 deletions
Loading

app/manifest/v3/chrome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"content_security_policy": {
3-
"extension_pages": "script-src 'self'; object-src 'none'; frame-ancestors 'none';"
3+
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-ancestors 'none';"
44
},
55
"externally_connectable": {
66
"matches": ["https://metamask.io/*"],

app/scripts/app-init.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
/* global chrome */
21
// This file is used only for manifest version 3
32

43
// Represents if importAllScripts has been run
54
// eslint-disable-next-line
65
let scriptsLoadInitiated = false;
7-
6+
const { chrome } = globalThis;
87
const testMode = process.env.IN_TEST;
98

109
const loadTimeLogs = [];

app/scripts/controllers/preferences.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export default class PreferencesController {
5656
useSafeChainsListValidation: true,
5757
// set to true means the dynamic list from the API is being used
5858
// set to false will be using the static list from contract-metadata
59-
useTokenDetection: false,
59+
useTokenDetection: opts?.initState?.useTokenDetection ?? true,
6060
useNftDetection: false,
6161
use4ByteResolution: true,
6262
useCurrencyRateCheck: true,
@@ -94,6 +94,7 @@ export default class PreferencesController {
9494
useNativeCurrencyAsPrimaryCurrency: true,
9595
hideZeroBalanceTokens: false,
9696
petnamesEnabled: true,
97+
redesignedConfirmationsEnabled: false,
9798
featureNotificationsEnabled: false,
9899
},
99100
// ENS decentralized website resolution

app/scripts/controllers/preferences.test.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,10 @@ describe('preferences controller', () => {
237237
});
238238

239239
describe('setUseTokenDetection', function () {
240-
it('should default to false', function () {
240+
it('should default to true for new users', function () {
241241
const state = preferencesController.store.getState();
242242

243-
expect(state.useTokenDetection).toStrictEqual(false);
243+
expect(state.useTokenDetection).toStrictEqual(true);
244244
});
245245

246246
it('should set the useTokenDetection property in state', () => {
@@ -249,6 +249,22 @@ describe('preferences controller', () => {
249249
preferencesController.store.getState().useTokenDetection,
250250
).toStrictEqual(true);
251251
});
252+
253+
it('should keep initial value of useTokenDetection for existing users', function () {
254+
const preferencesControllerExistingUser = new PreferencesController({
255+
initLangCode: 'en_US',
256+
tokenListController,
257+
initState: {
258+
useTokenDetection: false,
259+
},
260+
networkConfigurations: NETWORK_CONFIGURATION_DATA,
261+
onKeyringStateChange: (listener) => {
262+
onKeyringStateChangeListener = listener;
263+
},
264+
});
265+
const state = preferencesControllerExistingUser.store.getState();
266+
expect(state.useTokenDetection).toStrictEqual(false);
267+
});
252268
});
253269

254270
describe('setUseNftDetection', () => {

app/scripts/lib/createRPCMethodTrackingMiddleware.js

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
MetaMetricsEventName,
88
MetaMetricsEventUiCustomization,
99
} from '../../../shared/constants/metametrics';
10-
import { SECOND } from '../../../shared/constants/time';
1110

1211
import {
1312
BlockaidResultType,
@@ -25,18 +24,18 @@ import { getSnapAndHardwareInfoForMetrics } from './snap-keyring/metrics';
2524

2625
/**
2726
* These types determine how the method tracking middleware handles incoming
28-
* requests based on the method name. There are three options right now but
29-
* the types could be expanded to cover other options in the future.
27+
* requests based on the method name.
3028
*/
3129
const RATE_LIMIT_TYPES = {
32-
RATE_LIMITED: 'rate_limited',
30+
TIMEOUT: 'timeout',
3331
BLOCKED: 'blocked',
3432
NON_RATE_LIMITED: 'non_rate_limited',
33+
RANDOM_SAMPLE: 'random_sample',
3534
};
3635

3736
/**
3837
* This object maps a method name to a RATE_LIMIT_TYPE. If not in this map the
39-
* default is 'RATE_LIMITED'
38+
* default is RANDOM_SAMPLE
4039
*/
4140
const RATE_LIMIT_MAP = {
4241
[MESSAGE_TYPE.ETH_SIGN]: RATE_LIMIT_TYPES.NON_RATE_LIMITED,
@@ -47,9 +46,12 @@ const RATE_LIMIT_MAP = {
4746
[MESSAGE_TYPE.ETH_DECRYPT]: RATE_LIMIT_TYPES.NON_RATE_LIMITED,
4847
[MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY]:
4948
RATE_LIMIT_TYPES.NON_RATE_LIMITED,
50-
[MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS]: RATE_LIMIT_TYPES.RATE_LIMITED,
51-
[MESSAGE_TYPE.WALLET_REQUEST_PERMISSIONS]: RATE_LIMIT_TYPES.RATE_LIMITED,
49+
[MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS]: RATE_LIMIT_TYPES.TIMEOUT,
50+
[MESSAGE_TYPE.WALLET_REQUEST_PERMISSIONS]: RATE_LIMIT_TYPES.TIMEOUT,
5251
[MESSAGE_TYPE.SEND_METADATA]: RATE_LIMIT_TYPES.BLOCKED,
52+
[MESSAGE_TYPE.ETH_CHAIN_ID]: RATE_LIMIT_TYPES.BLOCKED,
53+
[MESSAGE_TYPE.ETH_ACCOUNTS]: RATE_LIMIT_TYPES.BLOCKED,
54+
[MESSAGE_TYPE.LOG_WEB3_SHIM_USAGE]: RATE_LIMIT_TYPES.BLOCKED,
5355
[MESSAGE_TYPE.GET_PROVIDER_STATE]: RATE_LIMIT_TYPES.BLOCKED,
5456
};
5557

@@ -107,7 +109,8 @@ const EVENT_NAME_MAP = {
107109
},
108110
};
109111

110-
const rateLimitTimeouts = {};
112+
const rateLimitTimeoutsByMethod = {};
113+
let globalRateLimitCount = 0;
111114

112115
///: BEGIN:ONLY_INCLUDE_IF(blockaid)
113116
/**
@@ -120,20 +123,29 @@ const rateLimitTimeouts = {};
120123
* MetaMetricsController
121124
* @param {Function} opts.getMetricsState - get the state of
122125
* MetaMetricsController
123-
* @param {number} [opts.rateLimitSeconds] - number of seconds to wait before
124-
* allowing another set of events to be tracked.
126+
* @param {number} [opts.rateLimitTimeout] - time, in milliseconds, to wait before
127+
* allowing another set of events to be tracked for methods rate limited by timeout.
128+
* @param {number} [opts.rateLimitSamplePercent] - percentage, in decimal, of events
129+
* that should be tracked for methods rate limited by random sample.
125130
* @param {Function} opts.getAccountType
126131
* @param {Function} opts.getDeviceModel
127132
* @param {RestrictedControllerMessenger} opts.snapAndHardwareMessenger
128133
* @param {AppStateController} opts.appStateController
134+
* @param {number} [opts.globalRateLimitTimeout] - time, in milliseconds, of the sliding
135+
* time window that should limit the number of method calls tracked to globalRateLimitMaxAmount.
136+
* @param {number} [opts.globalRateLimitMaxAmount] - max number of method calls that should
137+
* tracked within the globalRateLimitTimeout time window.
129138
* @returns {Function}
130139
*/
131140
///: END:ONLY_INCLUDE_IF
132141

133142
export default function createRPCMethodTrackingMiddleware({
134143
trackEvent,
135144
getMetricsState,
136-
rateLimitSeconds = 60 * 5,
145+
rateLimitTimeout = 60 * 5 * 1000, // 5 minutes
146+
rateLimitSamplePercent = 0.001, // 0.1%
147+
globalRateLimitTimeout = 60 * 5 * 1000, // 5 minutes
148+
globalRateLimitMaxAmount = 10, // max of events in the globalRateLimitTimeout window. pass 0 for no global rate limit
137149
getAccountType,
138150
getDeviceModel,
139151
snapAndHardwareMessenger,
@@ -148,14 +160,30 @@ export default function createRPCMethodTrackingMiddleware({
148160
) {
149161
const { origin, method } = req;
150162

151-
// Determine what type of rate limit to apply based on method
152163
const rateLimitType =
153-
RATE_LIMIT_MAP[method] ?? RATE_LIMIT_TYPES.RATE_LIMITED;
164+
RATE_LIMIT_MAP[method] ?? RATE_LIMIT_TYPES.RANDOM_SAMPLE;
165+
166+
let isRateLimited;
167+
switch (rateLimitType) {
168+
case RATE_LIMIT_TYPES.TIMEOUT:
169+
isRateLimited =
170+
typeof rateLimitTimeoutsByMethod[method] !== 'undefined';
171+
break;
172+
case RATE_LIMIT_TYPES.NON_RATE_LIMITED:
173+
isRateLimited = false;
174+
break;
175+
case RATE_LIMIT_TYPES.BLOCKED:
176+
isRateLimited = true;
177+
break;
178+
default:
179+
case RATE_LIMIT_TYPES.RANDOM_SAMPLE:
180+
isRateLimited = Math.random() >= rateLimitSamplePercent;
181+
break;
182+
}
154183

155-
// If the rateLimitType is RATE_LIMITED check the rateLimitTimeouts
156-
const rateLimited =
157-
rateLimitType === RATE_LIMIT_TYPES.RATE_LIMITED &&
158-
typeof rateLimitTimeouts[method] !== 'undefined';
184+
const isGlobalRateLimited =
185+
globalRateLimitMaxAmount > 0 &&
186+
globalRateLimitCount >= globalRateLimitMaxAmount;
159187

160188
// Get the participateInMetaMetrics state to determine if we should track
161189
// anything. This is extra redundancy because this value is checked in
@@ -173,10 +201,10 @@ export default function createRPCMethodTrackingMiddleware({
173201
const shouldTrackEvent =
174202
// Don't track if the request came from our own UI or background
175203
origin !== ORIGIN_METAMASK &&
176-
// Don't track if this is a blocked method
177-
rateLimitType !== RATE_LIMIT_TYPES.BLOCKED &&
178204
// Don't track if the rate limit has been hit
179-
rateLimited === false &&
205+
!isRateLimited &&
206+
// Don't track if the global rate limit has been hit
207+
!isGlobalRateLimited &&
180208
// Don't track if the user isn't participating in metametrics
181209
userParticipatingInMetaMetrics === true;
182210

@@ -258,9 +286,16 @@ export default function createRPCMethodTrackingMiddleware({
258286
properties: eventProperties,
259287
});
260288

261-
rateLimitTimeouts[method] = setTimeout(() => {
262-
delete rateLimitTimeouts[method];
263-
}, SECOND * rateLimitSeconds);
289+
if (rateLimitType === RATE_LIMIT_TYPES.TIMEOUT) {
290+
rateLimitTimeoutsByMethod[method] = setTimeout(() => {
291+
delete rateLimitTimeoutsByMethod[method];
292+
}, rateLimitTimeout);
293+
}
294+
295+
globalRateLimitCount += 1;
296+
setTimeout(() => {
297+
globalRateLimitCount -= 1;
298+
}, globalRateLimitTimeout);
264299
}
265300

266301
next(async (callback) => {

0 commit comments

Comments
 (0)