@metamask/assets-controllers 105.1.0 → 106.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -1
- package/dist/AccountTrackerController-method-action-types.cjs.map +1 -1
- package/dist/AccountTrackerController-method-action-types.d.cts +24 -1
- package/dist/AccountTrackerController-method-action-types.d.cts.map +1 -1
- package/dist/AccountTrackerController-method-action-types.d.mts +24 -1
- package/dist/AccountTrackerController-method-action-types.d.mts.map +1 -1
- package/dist/AccountTrackerController-method-action-types.mjs.map +1 -1
- package/dist/AccountTrackerController.cjs +2 -0
- package/dist/AccountTrackerController.cjs.map +1 -1
- package/dist/AccountTrackerController.d.cts.map +1 -1
- package/dist/AccountTrackerController.d.mts.map +1 -1
- package/dist/AccountTrackerController.mjs +2 -0
- package/dist/AccountTrackerController.mjs.map +1 -1
- package/dist/TokenBalancesController-method-action-types.cjs.map +1 -1
- package/dist/TokenBalancesController-method-action-types.d.cts +9 -1
- package/dist/TokenBalancesController-method-action-types.d.cts.map +1 -1
- package/dist/TokenBalancesController-method-action-types.d.mts +9 -1
- package/dist/TokenBalancesController-method-action-types.d.mts.map +1 -1
- package/dist/TokenBalancesController-method-action-types.mjs.map +1 -1
- package/dist/TokenBalancesController.cjs +19 -2
- package/dist/TokenBalancesController.cjs.map +1 -1
- package/dist/TokenBalancesController.d.cts.map +1 -1
- package/dist/TokenBalancesController.d.mts.map +1 -1
- package/dist/TokenBalancesController.mjs +20 -3
- package/dist/TokenBalancesController.mjs.map +1 -1
- package/dist/TokenDetectionController-method-action-types.cjs.map +1 -1
- package/dist/TokenDetectionController-method-action-types.d.cts +1 -1
- package/dist/TokenDetectionController-method-action-types.d.mts +1 -1
- package/dist/TokenDetectionController-method-action-types.mjs.map +1 -1
- package/dist/TokenDetectionController.cjs +137 -145
- package/dist/TokenDetectionController.cjs.map +1 -1
- package/dist/TokenDetectionController.d.cts +9 -13
- package/dist/TokenDetectionController.d.cts.map +1 -1
- package/dist/TokenDetectionController.d.mts +9 -13
- package/dist/TokenDetectionController.d.mts.map +1 -1
- package/dist/TokenDetectionController.mjs +138 -146
- package/dist/TokenDetectionController.mjs.map +1 -1
- package/dist/TokenListService.cjs +107 -0
- package/dist/TokenListService.cjs.map +1 -0
- package/dist/TokenListService.d.cts +40 -0
- package/dist/TokenListService.d.cts.map +1 -0
- package/dist/TokenListService.d.mts +40 -0
- package/dist/TokenListService.d.mts.map +1 -0
- package/dist/TokenListService.mjs +102 -0
- package/dist/TokenListService.mjs.map +1 -0
- package/dist/TokensController.cjs +49 -131
- package/dist/TokensController.cjs.map +1 -1
- package/dist/TokensController.d.cts +8 -6
- package/dist/TokensController.d.cts.map +1 -1
- package/dist/TokensController.d.mts +8 -6
- package/dist/TokensController.d.mts.map +1 -1
- package/dist/TokensController.mjs +49 -131
- package/dist/TokensController.mjs.map +1 -1
- package/dist/constants.cjs +32 -1
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +15 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +15 -0
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +31 -0
- package/dist/constants.mjs.map +1 -1
- package/dist/index.cjs +4 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/token-prices-service/codefi-v2.d.cts +1 -1
- package/dist/token-prices-service/codefi-v2.d.mts +1 -1
- package/package.json +7 -6
|
@@ -13,43 +13,15 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
var _TokenDetectionController_instances, _TokenDetectionController_intervalId, _TokenDetectionController_selectedAccountId,
|
|
16
|
+
var _TokenDetectionController_instances, _TokenDetectionController_intervalId, _TokenDetectionController_selectedAccountId, _TokenDetectionController_tokenListService, _TokenDetectionController_disabled, _TokenDetectionController_isUnlocked, _TokenDetectionController_isDetectionEnabledFromPreferences, _TokenDetectionController_useTokenDetection, _TokenDetectionController_useExternalServices, _TokenDetectionController_getBalancesInSingleCall, _TokenDetectionController_trackMetaMetricsEvent, _TokenDetectionController_registerEventListeners, _TokenDetectionController_stopPolling, _TokenDetectionController_startPolling, _TokenDetectionController_getCorrectNetworkClientIdByChainId, _TokenDetectionController_restartTokenDetection, _TokenDetectionController_getChainCacheForDetection, _TokenDetectionController_detectTokensUsingRpc, _TokenDetectionController_getSlicesOfTokensToDetect, _TokenDetectionController_getConvertedStaticMainnetTokenList, _TokenDetectionController_buildMusdTokenListToken, _TokenDetectionController_mergeMusdIntoTokenListMap, _TokenDetectionController_applyMusdDefaultToTokensChainsCache, _TokenDetectionController_includeMusdInTokenDetectionSlice, _TokenDetectionController_addDetectedTokens, _TokenDetectionController_getSelectedAccount, _TokenDetectionController_getSelectedAddress;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.TokenDetectionController = exports.controllerName = exports.
|
|
18
|
+
exports.TokenDetectionController = exports.controllerName = exports.STATIC_MAINNET_TOKEN_LIST = void 0;
|
|
19
19
|
const contract_metadata_1 = __importDefault(require("@metamask/contract-metadata"));
|
|
20
20
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
21
21
|
const polling_controller_1 = require("@metamask/polling-controller");
|
|
22
|
-
const lodash_1 = require("lodash");
|
|
23
22
|
const assetsUtil_1 = require("./assetsUtil.cjs");
|
|
24
23
|
const constants_1 = require("./constants.cjs");
|
|
25
24
|
const DEFAULT_INTERVAL = 180000;
|
|
26
|
-
/**
|
|
27
|
-
* Canonical contract address for MetaMask USD (mUSD) — same across every
|
|
28
|
-
* chain we deploy it to.
|
|
29
|
-
*/
|
|
30
|
-
const MUSD_ADDRESS = '0xaca92e438df0b2401ff60da7e4337b687a2435da';
|
|
31
|
-
/**
|
|
32
|
-
* Pre-built Token entry for mUSD — used when seeding default state.
|
|
33
|
-
*/
|
|
34
|
-
const MUSD_TOKEN = {
|
|
35
|
-
address: MUSD_ADDRESS,
|
|
36
|
-
decimals: 6,
|
|
37
|
-
symbol: 'mUSD',
|
|
38
|
-
name: 'MetaMask USD',
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* Hex chain IDs on which mUSD is deployed and should be added by default.
|
|
42
|
-
* - 0x1 — Ethereum mainnet (1)
|
|
43
|
-
* - 0xe708 — Linea (59144)
|
|
44
|
-
* - 0x8f — Monad mainnet (143)
|
|
45
|
-
* - 0x279f — Monad testnet (10143)
|
|
46
|
-
*/
|
|
47
|
-
const MUSD_SUPPORTED_CHAIN_IDS = new Set([
|
|
48
|
-
'0x1',
|
|
49
|
-
'0xe708',
|
|
50
|
-
'0x8f',
|
|
51
|
-
'0x279f',
|
|
52
|
-
]);
|
|
53
25
|
exports.STATIC_MAINNET_TOKEN_LIST = Object.entries(contract_metadata_1.default).reduce((acc, [base, contract]) => {
|
|
54
26
|
const { logo, erc20, erc721, ...tokenMetadata } = contract;
|
|
55
27
|
return {
|
|
@@ -62,21 +34,7 @@ exports.STATIC_MAINNET_TOKEN_LIST = Object.entries(contract_metadata_1.default).
|
|
|
62
34
|
},
|
|
63
35
|
};
|
|
64
36
|
}, {});
|
|
65
|
-
|
|
66
|
-
* Function that takes a TokensChainsCache object and maps chainId with TokenListMap.
|
|
67
|
-
*
|
|
68
|
-
* @param tokensChainsCache - TokensChainsCache input object
|
|
69
|
-
* @returns returns the map of chainId with TokenListMap
|
|
70
|
-
*/
|
|
71
|
-
function mapChainIdWithTokenListMap(tokensChainsCache) {
|
|
72
|
-
return (0, lodash_1.mapValues)(tokensChainsCache, (value) => {
|
|
73
|
-
if ((0, lodash_1.isObject)(value) && 'data' in value) {
|
|
74
|
-
return (0, lodash_1.get)(value, ['data']);
|
|
75
|
-
}
|
|
76
|
-
return value;
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
exports.mapChainIdWithTokenListMap = mapChainIdWithTokenListMap;
|
|
37
|
+
const MUSD_TOKEN_DETECTION_CHAIN_ID_SET = new Set(constants_1.MUSD_TOKEN_DETECTION_CHAIN_IDS);
|
|
80
38
|
exports.controllerName = 'TokenDetectionController';
|
|
81
39
|
const MESSENGER_EXPOSED_METHODS = [
|
|
82
40
|
'addDetectedTokensViaWs',
|
|
@@ -109,6 +67,7 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
109
67
|
*
|
|
110
68
|
* @param options - The controller options.
|
|
111
69
|
* @param options.messenger - The controller messenger.
|
|
70
|
+
* @param options.tokenListService - Shared service for fetching the token list per chain.
|
|
112
71
|
* @param options.disabled - If set to true, all network requests are blocked.
|
|
113
72
|
* @param options.interval - Polling interval used to fetch new token rates
|
|
114
73
|
* @param options.getBalancesInSingleCall - Gets the balances of a list of tokens for the given address.
|
|
@@ -116,7 +75,7 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
116
75
|
* @param options.useTokenDetection - Feature Switch for using token detection (default: true)
|
|
117
76
|
* @param options.useExternalServices - Feature Switch for using external services (default: false)
|
|
118
77
|
*/
|
|
119
|
-
constructor({ interval = DEFAULT_INTERVAL, disabled = true, getBalancesInSingleCall, trackMetaMetricsEvent, messenger, useTokenDetection = () => true, useExternalServices = () => true, }) {
|
|
78
|
+
constructor({ interval = DEFAULT_INTERVAL, disabled = true, getBalancesInSingleCall, trackMetaMetricsEvent, messenger, tokenListService, useTokenDetection = () => true, useExternalServices = () => true, }) {
|
|
120
79
|
super({
|
|
121
80
|
name: exports.controllerName,
|
|
122
81
|
messenger,
|
|
@@ -126,22 +85,19 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
126
85
|
_TokenDetectionController_instances.add(this);
|
|
127
86
|
_TokenDetectionController_intervalId.set(this, void 0);
|
|
128
87
|
_TokenDetectionController_selectedAccountId.set(this, void 0);
|
|
129
|
-
|
|
88
|
+
_TokenDetectionController_tokenListService.set(this, void 0);
|
|
130
89
|
_TokenDetectionController_disabled.set(this, void 0);
|
|
131
90
|
_TokenDetectionController_isUnlocked.set(this, void 0);
|
|
132
91
|
_TokenDetectionController_isDetectionEnabledFromPreferences.set(this, void 0);
|
|
133
92
|
_TokenDetectionController_useTokenDetection.set(this, void 0);
|
|
134
93
|
_TokenDetectionController_useExternalServices.set(this, void 0);
|
|
135
|
-
/** Tracks whether default tokens (mUSD) have been seeded for the current session. */
|
|
136
|
-
_TokenDetectionController_defaultTokensSeeded.set(this, false);
|
|
137
94
|
_TokenDetectionController_getBalancesInSingleCall.set(this, void 0);
|
|
138
95
|
_TokenDetectionController_trackMetaMetricsEvent.set(this, void 0);
|
|
139
96
|
messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
140
97
|
__classPrivateFieldSet(this, _TokenDetectionController_disabled, disabled, "f");
|
|
141
98
|
this.setIntervalLength(interval);
|
|
142
99
|
__classPrivateFieldSet(this, _TokenDetectionController_selectedAccountId, __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSelectedAccount).call(this).id, "f");
|
|
143
|
-
|
|
144
|
-
__classPrivateFieldSet(this, _TokenDetectionController_tokensChainsCache, tokensChainsCache, "f");
|
|
100
|
+
__classPrivateFieldSet(this, _TokenDetectionController_tokenListService, tokenListService, "f");
|
|
145
101
|
const { useTokenDetection: defaultUseTokenDetection } = this.messenger.call('PreferencesController:getState');
|
|
146
102
|
__classPrivateFieldSet(this, _TokenDetectionController_isDetectionEnabledFromPreferences, defaultUseTokenDetection, "f");
|
|
147
103
|
__classPrivateFieldSet(this, _TokenDetectionController_getBalancesInSingleCall, getBalancesInSingleCall, "f");
|
|
@@ -177,9 +133,6 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
177
133
|
*/
|
|
178
134
|
async start() {
|
|
179
135
|
this.enable();
|
|
180
|
-
// Seed mUSD as a default token via TokensController:addTokens. Runs
|
|
181
|
-
// once per session; idempotent because addTokens dedupes on address.
|
|
182
|
-
await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_seedDefaultTokens).call(this);
|
|
183
136
|
await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_startPolling).call(this);
|
|
184
137
|
}
|
|
185
138
|
/**
|
|
@@ -199,7 +152,7 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
199
152
|
});
|
|
200
153
|
}
|
|
201
154
|
/**
|
|
202
|
-
* For each token in the token list provided by the
|
|
155
|
+
* For each token in the token list provided by the TokenListService, checks the token's balance for the selected account address on the active network.
|
|
203
156
|
* On mainnet, if token detection is disabled in preferences, ERC20 token auto detection will be triggered for each contract address in the legacy token list from the @metamask/contract-metadata repo.
|
|
204
157
|
*
|
|
205
158
|
* @param options - Options for token detection.
|
|
@@ -256,18 +209,28 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
256
209
|
if (!__classPrivateFieldGet(this, _TokenDetectionController_useExternalServices, "f").call(this)) {
|
|
257
210
|
return;
|
|
258
211
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
212
|
+
let tokenListMap;
|
|
213
|
+
try {
|
|
214
|
+
tokenListMap = await __classPrivateFieldGet(this, _TokenDetectionController_tokenListService, "f").fetchTokensByChainId(chainId);
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// These methods return void; there is no token array to return.
|
|
218
|
+
// Gracefully exit so the caller is unaffected — the next polling cycle
|
|
219
|
+
// will retry the fetch.
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const chainCache = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_applyMusdDefaultToTokensChainsCache).call(this, chainId, {
|
|
223
|
+
[chainId]: { data: tokenListMap, timestamp: Date.now() },
|
|
224
|
+
});
|
|
225
|
+
const effectiveSlice = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_includeMusdInTokenDetectionSlice).call(this, tokensSlice, chainId);
|
|
263
226
|
const tokensWithBalance = [];
|
|
264
227
|
const eventTokensDetails = [];
|
|
265
|
-
for (const tokenAddress of
|
|
228
|
+
for (const tokenAddress of effectiveSlice) {
|
|
266
229
|
// Normalize addresses explicitly (don't assume input format)
|
|
267
230
|
const lowercaseTokenAddress = tokenAddress.toLowerCase();
|
|
268
231
|
const checksummedTokenAddress = (0, controller_utils_1.toChecksumHexAddress)(tokenAddress);
|
|
269
232
|
// Check map of validated tokens (cache keys are lowercase)
|
|
270
|
-
const tokenData =
|
|
233
|
+
const tokenData = chainCache[chainId]?.data?.[lowercaseTokenAddress];
|
|
271
234
|
if (!tokenData) {
|
|
272
235
|
continue;
|
|
273
236
|
}
|
|
@@ -323,18 +286,28 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
323
286
|
if (!__classPrivateFieldGet(this, _TokenDetectionController_useExternalServices, "f").call(this)) {
|
|
324
287
|
return;
|
|
325
288
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
289
|
+
let tokenListMap;
|
|
290
|
+
try {
|
|
291
|
+
tokenListMap = await __classPrivateFieldGet(this, _TokenDetectionController_tokenListService, "f").fetchTokensByChainId(chainId);
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// These methods return void; there is no token array to return.
|
|
295
|
+
// Gracefully exit so the caller is unaffected — the next polling cycle
|
|
296
|
+
// will retry the fetch.
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const chainCache = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_applyMusdDefaultToTokensChainsCache).call(this, chainId, {
|
|
300
|
+
[chainId]: { data: tokenListMap, timestamp: Date.now() },
|
|
301
|
+
});
|
|
330
302
|
const selectedAddress = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSelectedAddress).call(this);
|
|
331
303
|
// Get current token states to filter out already tracked/ignored tokens
|
|
332
304
|
const { allTokens, allIgnoredTokens } = this.messenger.call('TokensController:getState');
|
|
333
305
|
const existingTokenAddresses = (allTokens[chainId]?.[selectedAddress] ?? []).map((token) => token.address.toLowerCase());
|
|
334
306
|
const ignoredTokenAddresses = (allIgnoredTokens[chainId]?.[selectedAddress] ?? []).map((address) => address.toLowerCase());
|
|
307
|
+
const effectiveSlice = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_includeMusdInTokenDetectionSlice).call(this, tokensSlice, chainId);
|
|
335
308
|
const tokensWithBalance = [];
|
|
336
309
|
const eventTokensDetails = [];
|
|
337
|
-
for (const tokenAddress of
|
|
310
|
+
for (const tokenAddress of effectiveSlice) {
|
|
338
311
|
const lowercaseTokenAddress = tokenAddress.toLowerCase();
|
|
339
312
|
const checksummedTokenAddress = (0, controller_utils_1.toChecksumHexAddress)(tokenAddress);
|
|
340
313
|
// Skip tokens already in allTokens
|
|
@@ -346,7 +319,7 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
346
319
|
continue;
|
|
347
320
|
}
|
|
348
321
|
// Check map of validated tokens (cache keys are lowercase)
|
|
349
|
-
const tokenData =
|
|
322
|
+
const tokenData = chainCache[chainId]?.data?.[lowercaseTokenAddress];
|
|
350
323
|
if (!tokenData) {
|
|
351
324
|
continue;
|
|
352
325
|
}
|
|
@@ -380,7 +353,7 @@ class TokenDetectionController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
380
353
|
}
|
|
381
354
|
}
|
|
382
355
|
exports.TokenDetectionController = TokenDetectionController;
|
|
383
|
-
_TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_selectedAccountId = new WeakMap(),
|
|
356
|
+
_TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_selectedAccountId = new WeakMap(), _TokenDetectionController_tokenListService = new WeakMap(), _TokenDetectionController_disabled = new WeakMap(), _TokenDetectionController_isUnlocked = new WeakMap(), _TokenDetectionController_isDetectionEnabledFromPreferences = new WeakMap(), _TokenDetectionController_useTokenDetection = new WeakMap(), _TokenDetectionController_useExternalServices = new WeakMap(), _TokenDetectionController_getBalancesInSingleCall = new WeakMap(), _TokenDetectionController_trackMetaMetricsEvent = new WeakMap(), _TokenDetectionController_instances = new WeakSet(), _TokenDetectionController_registerEventListeners = function _TokenDetectionController_registerEventListeners() {
|
|
384
357
|
this.messenger.subscribe('KeyringController:unlock', () => {
|
|
385
358
|
__classPrivateFieldSet(this, _TokenDetectionController_isUnlocked, true, "f");
|
|
386
359
|
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_restartTokenDetection).call(this).catch(() => {
|
|
@@ -391,14 +364,6 @@ _TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_
|
|
|
391
364
|
__classPrivateFieldSet(this, _TokenDetectionController_isUnlocked, false, "f");
|
|
392
365
|
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_stopPolling).call(this);
|
|
393
366
|
});
|
|
394
|
-
this.messenger.subscribe('TokenListController:stateChange', ({ tokensChainsCache }) => {
|
|
395
|
-
const isEqualValues = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_compareTokensChainsCache).call(this, tokensChainsCache, __classPrivateFieldGet(this, _TokenDetectionController_tokensChainsCache, "f"));
|
|
396
|
-
if (!isEqualValues) {
|
|
397
|
-
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_restartTokenDetection).call(this).catch(() => {
|
|
398
|
-
// Silently handle token detection errors
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
367
|
this.messenger.subscribe('PreferencesController:stateChange', ({ useTokenDetection }) => {
|
|
403
368
|
const selectedAccount = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSelectedAccount).call(this);
|
|
404
369
|
const isDetectionChangedFromPreferences = __classPrivateFieldGet(this, _TokenDetectionController_isDetectionEnabledFromPreferences, "f") !== useTokenDetection;
|
|
@@ -417,13 +382,6 @@ _TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_
|
|
|
417
382
|
const isSelectedAccountIdChanged = __classPrivateFieldGet(this, _TokenDetectionController_selectedAccountId, "f") !== selectedAccount.id;
|
|
418
383
|
if (isSelectedAccountIdChanged) {
|
|
419
384
|
__classPrivateFieldSet(this, _TokenDetectionController_selectedAccountId, selectedAccount.id, "f");
|
|
420
|
-
// Re-seed mUSD for the newly selected account. addTokens only adds
|
|
421
|
-
// tokens for the currently selected account, so we need to re-run
|
|
422
|
-
// it whenever the active account changes.
|
|
423
|
-
__classPrivateFieldSet(this, _TokenDetectionController_defaultTokensSeeded, false, "f");
|
|
424
|
-
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_seedDefaultTokens).call(this).catch(() => {
|
|
425
|
-
// Silently handle default-token seeding errors
|
|
426
|
-
});
|
|
427
385
|
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_restartTokenDetection).call(this, {
|
|
428
386
|
selectedAddress: selectedAccount.address,
|
|
429
387
|
chainIds,
|
|
@@ -439,19 +397,6 @@ _TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_
|
|
|
439
397
|
// Silently handle token detection errors
|
|
440
398
|
});
|
|
441
399
|
});
|
|
442
|
-
// Re-seed mUSD whenever a network is added. Covers the case where the
|
|
443
|
-
// user adds a supported chain (e.g. Monad testnet) after the controller
|
|
444
|
-
// has already started — the chain wasn't configured at start() time so
|
|
445
|
-
// findNetworkClientIdByChainId would have skipped it.
|
|
446
|
-
this.messenger.subscribe('NetworkController:networkAdded', ({ chainId }) => {
|
|
447
|
-
if (!MUSD_SUPPORTED_CHAIN_IDS.has(chainId)) {
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
__classPrivateFieldSet(this, _TokenDetectionController_defaultTokensSeeded, false, "f");
|
|
451
|
-
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_seedDefaultTokens).call(this).catch(() => {
|
|
452
|
-
// Silently handle default-token seeding errors
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
400
|
}, _TokenDetectionController_stopPolling = function _TokenDetectionController_stopPolling() {
|
|
456
401
|
if (__classPrivateFieldGet(this, _TokenDetectionController_intervalId, "f")) {
|
|
457
402
|
clearInterval(__classPrivateFieldGet(this, _TokenDetectionController_intervalId, "f"));
|
|
@@ -471,11 +416,6 @@ async function _TokenDetectionController_startPolling() {
|
|
|
471
416
|
__classPrivateFieldSet(this, _TokenDetectionController_intervalId, setInterval(async () => {
|
|
472
417
|
await this.detectTokens();
|
|
473
418
|
}, this.getIntervalLength()), "f");
|
|
474
|
-
}, _TokenDetectionController_compareTokensChainsCache = function _TokenDetectionController_compareTokensChainsCache(tokensChainsCache, previousTokensChainsCache) {
|
|
475
|
-
const cleanPreviousTokensChainsCache = mapChainIdWithTokenListMap(previousTokensChainsCache);
|
|
476
|
-
const cleanTokensChainsCache = mapChainIdWithTokenListMap(tokensChainsCache);
|
|
477
|
-
const isEqualValues = (0, lodash_1.isEqual)(cleanTokensChainsCache, cleanPreviousTokensChainsCache);
|
|
478
|
-
return isEqualValues;
|
|
479
419
|
}, _TokenDetectionController_getCorrectNetworkClientIdByChainId = function _TokenDetectionController_getCorrectNetworkClientIdByChainId(chainIds) {
|
|
480
420
|
const { networkConfigurationsByChainId, selectedNetworkClientId } = this.messenger.call('NetworkController:getState');
|
|
481
421
|
if (!chainIds) {
|
|
@@ -510,30 +450,41 @@ async function _TokenDetectionController_restartTokenDetection({ selectedAddress
|
|
|
510
450
|
selectedAddress,
|
|
511
451
|
});
|
|
512
452
|
this.setIntervalLength(DEFAULT_INTERVAL);
|
|
513
|
-
},
|
|
453
|
+
}, _TokenDetectionController_getChainCacheForDetection =
|
|
454
|
+
/**
|
|
455
|
+
* Returns the token cache for `chainId` if detection should proceed, or `null` if it
|
|
456
|
+
* should be skipped. Each call fetches a fresh snapshot from `TokenListService` (which
|
|
457
|
+
* may serve from its in-memory cache) so concurrent calls for different chains never
|
|
458
|
+
* overwrite each other's data.
|
|
459
|
+
*
|
|
460
|
+
* @param chainId - The chain ID to build a detection cache for.
|
|
461
|
+
* @returns A `TokensChainsCache` scoped to `chainId`, or `null` when detection should be skipped.
|
|
462
|
+
*/
|
|
463
|
+
async function _TokenDetectionController_getChainCacheForDetection(chainId) {
|
|
514
464
|
if (!(0, assetsUtil_1.isTokenDetectionSupportedForNetwork)(chainId)) {
|
|
515
|
-
return
|
|
465
|
+
return null;
|
|
516
466
|
}
|
|
517
467
|
if (!__classPrivateFieldGet(this, _TokenDetectionController_isDetectionEnabledFromPreferences, "f") &&
|
|
518
468
|
chainId !== controller_utils_1.ChainId.mainnet) {
|
|
519
|
-
return
|
|
469
|
+
return null;
|
|
520
470
|
}
|
|
521
471
|
const isMainnetDetectionInactive = !__classPrivateFieldGet(this, _TokenDetectionController_isDetectionEnabledFromPreferences, "f") && chainId === controller_utils_1.ChainId.mainnet;
|
|
522
472
|
if (isMainnetDetectionInactive) {
|
|
523
|
-
|
|
524
|
-
}
|
|
525
|
-
else {
|
|
526
|
-
const { tokensChainsCache } = this.messenger.call('TokenListController:getState');
|
|
527
|
-
__classPrivateFieldSet(this, _TokenDetectionController_tokensChainsCache, tokensChainsCache ?? {}, "f");
|
|
473
|
+
return __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getConvertedStaticMainnetTokenList).call(this);
|
|
528
474
|
}
|
|
529
|
-
|
|
475
|
+
const tokenListMap = await __classPrivateFieldGet(this, _TokenDetectionController_tokenListService, "f").fetchTokensByChainId(chainId);
|
|
476
|
+
return __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_applyMusdDefaultToTokensChainsCache).call(this, chainId, {
|
|
477
|
+
[chainId]: { data: tokenListMap, timestamp: Date.now() },
|
|
478
|
+
});
|
|
530
479
|
}, _TokenDetectionController_detectTokensUsingRpc = async function _TokenDetectionController_detectTokensUsingRpc(chainsToDetectUsingRpc, addressToDetect) {
|
|
531
480
|
for (const { chainId, networkClientId } of chainsToDetectUsingRpc) {
|
|
532
|
-
|
|
481
|
+
const chainCache = await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getChainCacheForDetection).call(this, chainId);
|
|
482
|
+
if (!chainCache) {
|
|
533
483
|
continue;
|
|
534
484
|
}
|
|
535
485
|
const tokenCandidateSlices = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSlicesOfTokensToDetect).call(this, {
|
|
536
486
|
chainId,
|
|
487
|
+
chainCache,
|
|
537
488
|
selectedAddress: addressToDetect,
|
|
538
489
|
});
|
|
539
490
|
const tokenDetectionPromises = tokenCandidateSlices.map((tokensSlice) => __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_addDetectedTokens).call(this, {
|
|
@@ -541,10 +492,11 @@ async function _TokenDetectionController_restartTokenDetection({ selectedAddress
|
|
|
541
492
|
selectedAddress: addressToDetect,
|
|
542
493
|
networkClientId,
|
|
543
494
|
chainId,
|
|
495
|
+
chainCache,
|
|
544
496
|
}));
|
|
545
497
|
await Promise.all(tokenDetectionPromises);
|
|
546
498
|
}
|
|
547
|
-
}, _TokenDetectionController_getSlicesOfTokensToDetect = function _TokenDetectionController_getSlicesOfTokensToDetect({ chainId, selectedAddress, }) {
|
|
499
|
+
}, _TokenDetectionController_getSlicesOfTokensToDetect = function _TokenDetectionController_getSlicesOfTokensToDetect({ chainId, chainCache, selectedAddress, }) {
|
|
548
500
|
const { allTokens, allDetectedTokens, allIgnoredTokens } = this.messenger.call('TokensController:getState');
|
|
549
501
|
const [tokensAddresses, detectedTokensAddresses, ignoredTokensAddresses] = [
|
|
550
502
|
allTokens,
|
|
@@ -552,7 +504,7 @@ async function _TokenDetectionController_restartTokenDetection({ selectedAddress
|
|
|
552
504
|
allIgnoredTokens,
|
|
553
505
|
].map((tokens) => (tokens[chainId]?.[selectedAddress] ?? []).map((value) => typeof value === 'string' ? value : value.address));
|
|
554
506
|
const tokensToDetect = [];
|
|
555
|
-
for (const tokenAddress of Object.keys(
|
|
507
|
+
for (const tokenAddress of Object.keys(chainCache[chainId]?.data ?? {})) {
|
|
556
508
|
if ([
|
|
557
509
|
tokensAddresses,
|
|
558
510
|
detectedTokensAddresses,
|
|
@@ -578,50 +530,66 @@ async function _TokenDetectionController_restartTokenDetection({ selectedAddress
|
|
|
578
530
|
iconUrl: value?.iconUrl,
|
|
579
531
|
},
|
|
580
532
|
}), {});
|
|
533
|
+
const dataWithMusd = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_mergeMusdIntoTokenListMap).call(this, controller_utils_1.ChainId.mainnet, data);
|
|
581
534
|
return {
|
|
582
535
|
'0x1': {
|
|
583
|
-
data,
|
|
536
|
+
data: dataWithMusd,
|
|
584
537
|
timestamp: 0,
|
|
585
538
|
},
|
|
586
539
|
};
|
|
587
|
-
},
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
540
|
+
}, _TokenDetectionController_buildMusdTokenListToken = function _TokenDetectionController_buildMusdTokenListToken(chainId) {
|
|
541
|
+
const meta = constants_1.MUSD_TOKEN_METADATA_BY_CHAIN[chainId];
|
|
542
|
+
return {
|
|
543
|
+
address: constants_1.MUSD_ERC20_ADDRESS_LOWER,
|
|
544
|
+
name: meta.name,
|
|
545
|
+
symbol: meta.symbol,
|
|
546
|
+
decimals: meta.decimals,
|
|
547
|
+
aggregators: [...meta.aggregators],
|
|
548
|
+
iconUrl: (0, assetsUtil_1.formatIconUrlWithProxy)({
|
|
549
|
+
chainId,
|
|
550
|
+
tokenAddress: constants_1.MUSD_ERC20_ADDRESS_LOWER,
|
|
551
|
+
}),
|
|
552
|
+
occurrences: 999,
|
|
553
|
+
};
|
|
554
|
+
}, _TokenDetectionController_mergeMusdIntoTokenListMap = function _TokenDetectionController_mergeMusdIntoTokenListMap(chainId, data) {
|
|
555
|
+
return {
|
|
556
|
+
...data,
|
|
557
|
+
[constants_1.MUSD_ERC20_ADDRESS_LOWER]: __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_buildMusdTokenListToken).call(this, chainId),
|
|
558
|
+
};
|
|
559
|
+
}, _TokenDetectionController_applyMusdDefaultToTokensChainsCache = function _TokenDetectionController_applyMusdDefaultToTokensChainsCache(chainId, cache) {
|
|
560
|
+
if (!MUSD_TOKEN_DETECTION_CHAIN_ID_SET.has(chainId)) {
|
|
561
|
+
return cache;
|
|
602
562
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
// Silently handle per-chain seeding errors so one failure does not
|
|
615
|
-
// block seeding on the remaining supported chains.
|
|
616
|
-
}
|
|
563
|
+
const existing = cache[chainId];
|
|
564
|
+
return {
|
|
565
|
+
...cache,
|
|
566
|
+
[chainId]: {
|
|
567
|
+
data: __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_mergeMusdIntoTokenListMap).call(this, chainId, existing?.data ?? {}),
|
|
568
|
+
timestamp: existing?.timestamp ?? 0,
|
|
569
|
+
},
|
|
570
|
+
};
|
|
571
|
+
}, _TokenDetectionController_includeMusdInTokenDetectionSlice = function _TokenDetectionController_includeMusdInTokenDetectionSlice(tokensSlice, chainId) {
|
|
572
|
+
if (!MUSD_TOKEN_DETECTION_CHAIN_ID_SET.has(chainId)) {
|
|
573
|
+
return tokensSlice;
|
|
617
574
|
}
|
|
618
|
-
|
|
575
|
+
if (tokensSlice.some((a) => (0, controller_utils_1.isEqualCaseInsensitive)(a, constants_1.MUSD_ERC20_ADDRESS_LOWER))) {
|
|
576
|
+
return tokensSlice;
|
|
577
|
+
}
|
|
578
|
+
return [...tokensSlice, constants_1.MUSD_ERC20_ADDRESS_LOWER];
|
|
579
|
+
}, _TokenDetectionController_addDetectedTokens = async function _TokenDetectionController_addDetectedTokens({ tokensSlice, selectedAddress, networkClientId, chainId, chainCache, }) {
|
|
619
580
|
await (0, controller_utils_1.safelyExecute)(async () => {
|
|
620
581
|
const balances = await __classPrivateFieldGet(this, _TokenDetectionController_getBalancesInSingleCall, "f").call(this, selectedAddress, tokensSlice, networkClientId);
|
|
582
|
+
const chainData = chainCache[chainId]?.data ?? {};
|
|
621
583
|
const tokensWithBalance = [];
|
|
622
584
|
const eventTokensDetails = [];
|
|
623
585
|
for (const nonZeroTokenAddress of Object.keys(balances)) {
|
|
624
|
-
|
|
586
|
+
// chainData keys are lowercase (normalised by buildTokenListMap);
|
|
587
|
+
// balance keys are checksummed, so normalise before lookup.
|
|
588
|
+
const tokenListEntry = chainData[nonZeroTokenAddress.toLowerCase()];
|
|
589
|
+
if (!tokenListEntry) {
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
const { decimals, symbol, aggregators, iconUrl, name, rwaData } = tokenListEntry;
|
|
625
593
|
eventTokensDetails.push(`${symbol} - ${nonZeroTokenAddress}`);
|
|
626
594
|
tokensWithBalance.push({
|
|
627
595
|
address: nonZeroTokenAddress,
|
|
@@ -634,6 +602,30 @@ async function _TokenDetectionController_seedDefaultTokens() {
|
|
|
634
602
|
...(rwaData && { rwaData }),
|
|
635
603
|
});
|
|
636
604
|
}
|
|
605
|
+
// mUSD is always in the chain token cache on supported networks, but
|
|
606
|
+
// getBalancesInSingleCall omits zero balances; still add mUSD so the wallet
|
|
607
|
+
// shows the asset (balance updates via the usual balance pipeline).
|
|
608
|
+
if (MUSD_TOKEN_DETECTION_CHAIN_ID_SET.has(chainId)) {
|
|
609
|
+
const musdInSlice = tokensSlice.some((addr) => (0, controller_utils_1.isEqualCaseInsensitive)(addr, constants_1.MUSD_ERC20_ADDRESS_LOWER));
|
|
610
|
+
const musdHasNonZeroFromRpc = Object.keys(balances).some((addr) => (0, controller_utils_1.isEqualCaseInsensitive)(addr, constants_1.MUSD_ERC20_ADDRESS_LOWER));
|
|
611
|
+
if (musdInSlice && !musdHasNonZeroFromRpc) {
|
|
612
|
+
const musdListToken = Object.entries(chainData).find(([key]) => (0, controller_utils_1.isEqualCaseInsensitive)(key, constants_1.MUSD_ERC20_ADDRESS_LOWER))?.[1];
|
|
613
|
+
if (musdListToken) {
|
|
614
|
+
const { decimals, symbol, aggregators, iconUrl, name, rwaData } = musdListToken;
|
|
615
|
+
eventTokensDetails.push(`${symbol} - ${constants_1.MUSD_ERC20_ADDRESS_LOWER}`);
|
|
616
|
+
tokensWithBalance.push({
|
|
617
|
+
address: constants_1.MUSD_ERC20_ADDRESS_LOWER,
|
|
618
|
+
decimals,
|
|
619
|
+
symbol,
|
|
620
|
+
aggregators,
|
|
621
|
+
image: iconUrl,
|
|
622
|
+
isERC721: false,
|
|
623
|
+
name,
|
|
624
|
+
...(rwaData && { rwaData }),
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
637
629
|
if (tokensWithBalance.length) {
|
|
638
630
|
__classPrivateFieldGet(this, _TokenDetectionController_trackMetaMetricsEvent, "f").call(this, {
|
|
639
631
|
event: 'Token Detected',
|