@metamask/assets-controllers 42.0.0 → 43.1.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 +24 -1
- package/dist/AccountTrackerController.cjs +30 -10
- package/dist/AccountTrackerController.cjs.map +1 -1
- package/dist/AccountTrackerController.d.cts +14 -9
- package/dist/AccountTrackerController.d.cts.map +1 -1
- package/dist/AccountTrackerController.d.mts +14 -9
- package/dist/AccountTrackerController.d.mts.map +1 -1
- package/dist/AccountTrackerController.mjs +30 -10
- package/dist/AccountTrackerController.mjs.map +1 -1
- package/dist/AssetsContractController.cjs +61 -1
- package/dist/AssetsContractController.cjs.map +1 -1
- package/dist/AssetsContractController.d.cts +13 -0
- package/dist/AssetsContractController.d.cts.map +1 -1
- package/dist/AssetsContractController.d.mts +13 -0
- package/dist/AssetsContractController.d.mts.map +1 -1
- package/dist/AssetsContractController.mjs +61 -1
- package/dist/AssetsContractController.mjs.map +1 -1
- package/dist/CurrencyRateController.d.cts +4 -4
- package/dist/CurrencyRateController.d.mts +4 -4
- package/dist/RatesController/RatesController.cjs +12 -1
- package/dist/RatesController/RatesController.cjs.map +1 -1
- package/dist/RatesController/RatesController.d.cts +8 -1
- package/dist/RatesController/RatesController.d.cts.map +1 -1
- package/dist/RatesController/RatesController.d.mts +8 -1
- package/dist/RatesController/RatesController.d.mts.map +1 -1
- package/dist/RatesController/RatesController.mjs +12 -1
- package/dist/RatesController/RatesController.mjs.map +1 -1
- package/dist/TokenDetectionController.cjs +191 -127
- package/dist/TokenDetectionController.cjs.map +1 -1
- package/dist/TokenDetectionController.d.cts +20 -11
- package/dist/TokenDetectionController.d.cts.map +1 -1
- package/dist/TokenDetectionController.d.mts +20 -11
- package/dist/TokenDetectionController.d.mts.map +1 -1
- package/dist/TokenDetectionController.mjs +190 -127
- package/dist/TokenDetectionController.mjs.map +1 -1
- package/dist/TokenListController.cjs +60 -53
- package/dist/TokenListController.cjs.map +1 -1
- package/dist/TokenListController.d.cts +25 -14
- package/dist/TokenListController.d.cts.map +1 -1
- package/dist/TokenListController.d.mts +25 -14
- package/dist/TokenListController.d.mts.map +1 -1
- package/dist/TokenListController.mjs +60 -53
- package/dist/TokenListController.mjs.map +1 -1
- package/dist/TokenRatesController.d.cts +4 -4
- package/dist/TokenRatesController.d.mts +4 -4
- package/dist/TokensController.cjs +7 -4
- package/dist/TokensController.cjs.map +1 -1
- package/dist/TokensController.d.cts.map +1 -1
- package/dist/TokensController.d.mts.map +1 -1
- package/dist/TokensController.mjs +7 -4
- package/dist/TokensController.mjs.map +1 -1
- package/dist/assetsUtil.cjs +13 -1
- package/dist/assetsUtil.cjs.map +1 -1
- package/dist/assetsUtil.d.cts +7 -0
- package/dist/assetsUtil.d.cts.map +1 -1
- package/dist/assetsUtil.d.mts +7 -0
- package/dist/assetsUtil.d.mts.map +1 -1
- package/dist/assetsUtil.mjs +12 -0
- package/dist/assetsUtil.mjs.map +1 -1
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.cjs +18 -0
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.cjs.map +1 -1
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.d.cts.map +1 -1
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.d.mts.map +1 -1
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.mjs +18 -0
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.mjs.map +1 -1
- package/package.json +9 -9
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _TokenDetectionController_instances, _TokenDetectionController_intervalId, _TokenDetectionController_selectedAccountId, _TokenDetectionController_networkClientId, _TokenDetectionController_tokensChainsCache, _TokenDetectionController_disabled, _TokenDetectionController_isUnlocked, _TokenDetectionController_isDetectionEnabledFromPreferences, _TokenDetectionController_isDetectionEnabledForNetwork, _TokenDetectionController_getBalancesInSingleCall, _TokenDetectionController_trackMetaMetricsEvent, _TokenDetectionController_accountsAPI, _TokenDetectionController_registerEventListeners, _TokenDetectionController_stopPolling, _TokenDetectionController_startPolling, _TokenDetectionController_compareTokensChainsCache, _TokenDetectionController_getCorrectChainIdAndNetworkClientId, _TokenDetectionController_restartTokenDetection, _TokenDetectionController_getSlicesOfTokensToDetect, _TokenDetectionController_getConvertedStaticMainnetTokenList, _TokenDetectionController_addDetectedTokensViaAPI, _TokenDetectionController_addDetectedTokens, _TokenDetectionController_getSelectedAccount, _TokenDetectionController_getSelectedAddress;
|
|
12
|
+
var _TokenDetectionController_instances, _TokenDetectionController_intervalId, _TokenDetectionController_selectedAccountId, _TokenDetectionController_networkClientId, _TokenDetectionController_tokensChainsCache, _TokenDetectionController_disabled, _TokenDetectionController_isUnlocked, _TokenDetectionController_isDetectionEnabledFromPreferences, _TokenDetectionController_isDetectionEnabledForNetwork, _TokenDetectionController_getBalancesInSingleCall, _TokenDetectionController_trackMetaMetricsEvent, _TokenDetectionController_accountsAPI, _TokenDetectionController_registerEventListeners, _TokenDetectionController_stopPolling, _TokenDetectionController_startPolling, _TokenDetectionController_compareTokensChainsCache, _TokenDetectionController_getCorrectNetworkClientIdByChainId, _TokenDetectionController_getCorrectChainIdAndNetworkClientId, _TokenDetectionController_restartTokenDetection, _TokenDetectionController_getChainsToDetect, _TokenDetectionController_attemptAccountAPIDetection, _TokenDetectionController_addChainsToRpcDetection, _TokenDetectionController_shouldDetectTokens, _TokenDetectionController_detectTokensUsingRpc, _TokenDetectionController_getSlicesOfTokensToDetect, _TokenDetectionController_getConvertedStaticMainnetTokenList, _TokenDetectionController_addDetectedTokensViaAPI, _TokenDetectionController_filterAndBuildTokensWithBalance, _TokenDetectionController_addDetectedTokens, _TokenDetectionController_getSelectedAccount, _TokenDetectionController_getSelectedAddress;
|
|
13
13
|
function $importDefault(module) {
|
|
14
14
|
if (module?.__esModule) {
|
|
15
15
|
return module.default;
|
|
@@ -43,7 +43,7 @@ export const STATIC_MAINNET_TOKEN_LIST = Object.entries(contractMap).reduce((acc
|
|
|
43
43
|
* @param tokensChainsCache - TokensChainsCache input object
|
|
44
44
|
* @returns returns the map of chainId with TokenListMap
|
|
45
45
|
*/
|
|
46
|
-
function mapChainIdWithTokenListMap(tokensChainsCache) {
|
|
46
|
+
export function mapChainIdWithTokenListMap(tokensChainsCache) {
|
|
47
47
|
return mapValues(tokensChainsCache, (value) => {
|
|
48
48
|
if (isObject(value) && 'data' in value) {
|
|
49
49
|
return get(value, ['data']);
|
|
@@ -110,18 +110,15 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
110
110
|
this.supportedNetworksCache = result;
|
|
111
111
|
return result;
|
|
112
112
|
},
|
|
113
|
-
async
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const chainIdNumber = hexToNumber(chainId);
|
|
118
|
-
const supportedNetworks = await this.getSupportedNetworks();
|
|
119
|
-
if (!supportedNetworks || !supportedNetworks.includes(chainIdNumber)) {
|
|
113
|
+
async getMultiNetworksBalances(address, chainIds, supportedNetworks) {
|
|
114
|
+
const chainIdNumbers = chainIds.map((chainId) => hexToNumber(chainId));
|
|
115
|
+
if (!supportedNetworks ||
|
|
116
|
+
!chainIdNumbers.every((id) => supportedNetworks.includes(id))) {
|
|
120
117
|
const supportedNetworksErrStr = (supportedNetworks ?? []).toString();
|
|
121
|
-
throw new Error(`Unsupported Network: supported networks ${supportedNetworksErrStr},
|
|
118
|
+
throw new Error(`Unsupported Network: supported networks ${supportedNetworksErrStr}, requested networks: ${chainIdNumbers.toString()}`);
|
|
122
119
|
}
|
|
123
120
|
const result = await fetchMultiChainBalances(address, {
|
|
124
|
-
networks:
|
|
121
|
+
networks: chainIdNumbers,
|
|
125
122
|
}, this.platform);
|
|
126
123
|
return result.balances;
|
|
127
124
|
},
|
|
@@ -177,12 +174,12 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
177
174
|
this.disable();
|
|
178
175
|
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_stopPolling).call(this);
|
|
179
176
|
}
|
|
180
|
-
async _executePoll({
|
|
177
|
+
async _executePoll({ chainIds, address, }) {
|
|
181
178
|
if (!this.isActive) {
|
|
182
179
|
return;
|
|
183
180
|
}
|
|
184
181
|
await this.detectTokens({
|
|
185
|
-
|
|
182
|
+
chainIds,
|
|
186
183
|
selectedAddress: address,
|
|
187
184
|
});
|
|
188
185
|
}
|
|
@@ -191,51 +188,35 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
191
188
|
* 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.
|
|
192
189
|
*
|
|
193
190
|
* @param options - Options for token detection.
|
|
194
|
-
* @param options.
|
|
191
|
+
* @param options.chainIds - The chain IDs of the network client to use.
|
|
195
192
|
* @param options.selectedAddress - the selectedAddress against which to detect for token balances.
|
|
196
193
|
*/
|
|
197
|
-
async detectTokens({
|
|
194
|
+
async detectTokens({ chainIds, selectedAddress, } = {}) {
|
|
198
195
|
if (!this.isActive) {
|
|
199
196
|
return;
|
|
200
197
|
}
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return;
|
|
198
|
+
const addressToDetect = selectedAddress ?? __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSelectedAddress).call(this);
|
|
199
|
+
const clientNetworks = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getCorrectNetworkClientIdByChainId).call(this, chainIds);
|
|
200
|
+
let supportedNetworks;
|
|
201
|
+
if (__classPrivateFieldGet(this, _TokenDetectionController_accountsAPI, "f").isAccountsAPIEnabled) {
|
|
202
|
+
supportedNetworks = await __classPrivateFieldGet(this, _TokenDetectionController_accountsAPI, "f").getSupportedNetworks();
|
|
207
203
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
const { chainsToDetectUsingRpc, chainsToDetectUsingAccountAPI } = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getChainsToDetect).call(this, clientNetworks, supportedNetworks);
|
|
205
|
+
// Try detecting tokens via Account API first if conditions allow
|
|
206
|
+
if (supportedNetworks && chainsToDetectUsingAccountAPI.length > 0) {
|
|
207
|
+
const apiResult = await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_attemptAccountAPIDetection).call(this, chainsToDetectUsingAccountAPI, addressToDetect, supportedNetworks);
|
|
208
|
+
// If API succeeds and no chains are left for RPC detection, we can return early
|
|
209
|
+
if (apiResult?.result === 'success' &&
|
|
210
|
+
chainsToDetectUsingRpc.length === 0) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// If API fails or chainsToDetectUsingRpc still has items, add chains to RPC detection
|
|
214
|
+
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_addChainsToRpcDetection).call(this, chainsToDetectUsingRpc, chainsToDetectUsingAccountAPI, clientNetworks);
|
|
211
215
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
__classPrivateFieldSet(this, _TokenDetectionController_tokensChainsCache, isTokenDetectionInactiveInMainnet
|
|
216
|
-
? __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getConvertedStaticMainnetTokenList).call(this)
|
|
217
|
-
: tokensChainsCache ?? {}, "f");
|
|
218
|
-
const tokenCandidateSlices = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSlicesOfTokensToDetect).call(this, {
|
|
219
|
-
chainId: chainIdAgainstWhichToDetect,
|
|
220
|
-
selectedAddress: addressAgainstWhichToDetect,
|
|
221
|
-
});
|
|
222
|
-
// Attempt Accounts API Detection
|
|
223
|
-
const accountAPIResult = await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_addDetectedTokensViaAPI).call(this, {
|
|
224
|
-
chainId: chainIdAgainstWhichToDetect,
|
|
225
|
-
selectedAddress: addressAgainstWhichToDetect,
|
|
226
|
-
tokenCandidateSlices,
|
|
227
|
-
});
|
|
228
|
-
if (accountAPIResult?.result === 'success') {
|
|
229
|
-
return;
|
|
216
|
+
// Proceed with RPC detection if there are chains remaining in chainsToDetectUsingRpc
|
|
217
|
+
if (chainsToDetectUsingRpc.length > 0) {
|
|
218
|
+
await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_detectTokensUsingRpc).call(this, chainsToDetectUsingRpc, addressToDetect);
|
|
230
219
|
}
|
|
231
|
-
// Attempt RPC Detection
|
|
232
|
-
const tokenDetectionPromises = tokenCandidateSlices.map((tokensSlice) => __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_addDetectedTokens).call(this, {
|
|
233
|
-
tokensSlice,
|
|
234
|
-
selectedAddress: addressAgainstWhichToDetect,
|
|
235
|
-
networkClientId: networkClientIdAgainstWhichToDetect,
|
|
236
|
-
chainId: chainIdAgainstWhichToDetect,
|
|
237
|
-
}));
|
|
238
|
-
await Promise.all(tokenDetectionPromises);
|
|
239
220
|
}
|
|
240
221
|
}
|
|
241
222
|
_TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_selectedAccountId = new WeakMap(), _TokenDetectionController_networkClientId = new WeakMap(), _TokenDetectionController_tokensChainsCache = new WeakMap(), _TokenDetectionController_disabled = new WeakMap(), _TokenDetectionController_isUnlocked = new WeakMap(), _TokenDetectionController_isDetectionEnabledFromPreferences = new WeakMap(), _TokenDetectionController_isDetectionEnabledForNetwork = new WeakMap(), _TokenDetectionController_getBalancesInSingleCall = new WeakMap(), _TokenDetectionController_trackMetaMetricsEvent = new WeakMap(), _TokenDetectionController_accountsAPI = new WeakMap(), _TokenDetectionController_instances = new WeakSet(), _TokenDetectionController_registerEventListeners = function _TokenDetectionController_registerEventListeners() {
|
|
@@ -283,20 +264,6 @@ _TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_
|
|
|
283
264
|
});
|
|
284
265
|
}
|
|
285
266
|
});
|
|
286
|
-
this.messagingSystem.subscribe('NetworkController:networkDidChange',
|
|
287
|
-
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
288
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
289
|
-
async ({ selectedNetworkClientId }) => {
|
|
290
|
-
const isNetworkClientIdChanged = __classPrivateFieldGet(this, _TokenDetectionController_networkClientId, "f") !== selectedNetworkClientId;
|
|
291
|
-
const { chainId: newChainId } = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getCorrectChainIdAndNetworkClientId).call(this, selectedNetworkClientId);
|
|
292
|
-
__classPrivateFieldSet(this, _TokenDetectionController_isDetectionEnabledForNetwork, isTokenDetectionSupportedForNetwork(newChainId), "f");
|
|
293
|
-
if (isNetworkClientIdChanged && __classPrivateFieldGet(this, _TokenDetectionController_isDetectionEnabledForNetwork, "f")) {
|
|
294
|
-
__classPrivateFieldSet(this, _TokenDetectionController_networkClientId, selectedNetworkClientId, "f");
|
|
295
|
-
await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_restartTokenDetection).call(this, {
|
|
296
|
-
networkClientId: __classPrivateFieldGet(this, _TokenDetectionController_networkClientId, "f"),
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
267
|
}, _TokenDetectionController_stopPolling = function _TokenDetectionController_stopPolling() {
|
|
301
268
|
if (__classPrivateFieldGet(this, _TokenDetectionController_intervalId, "f")) {
|
|
302
269
|
clearInterval(__classPrivateFieldGet(this, _TokenDetectionController_intervalId, "f"));
|
|
@@ -321,16 +288,26 @@ async function _TokenDetectionController_startPolling() {
|
|
|
321
288
|
const cleanTokensChainsCache = mapChainIdWithTokenListMap(tokensChainsCache);
|
|
322
289
|
const isEqualValues = isEqual(cleanTokensChainsCache, cleanPreviousTokensChainsCache);
|
|
323
290
|
return isEqualValues;
|
|
324
|
-
},
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
291
|
+
}, _TokenDetectionController_getCorrectNetworkClientIdByChainId = function _TokenDetectionController_getCorrectNetworkClientIdByChainId(chainIds) {
|
|
292
|
+
const { networkConfigurationsByChainId, selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|
|
293
|
+
if (!chainIds) {
|
|
294
|
+
const networkConfiguration = this.messagingSystem.call('NetworkController:getNetworkConfigurationByNetworkClientId', selectedNetworkClientId);
|
|
295
|
+
return [
|
|
296
|
+
{
|
|
297
|
+
chainId: networkConfiguration?.chainId ?? ChainId.mainnet,
|
|
298
|
+
networkClientId: selectedNetworkClientId,
|
|
299
|
+
},
|
|
300
|
+
];
|
|
333
301
|
}
|
|
302
|
+
return chainIds.map((chainId) => {
|
|
303
|
+
const configuration = networkConfigurationsByChainId[chainId];
|
|
304
|
+
return {
|
|
305
|
+
chainId,
|
|
306
|
+
networkClientId: configuration.rpcEndpoints[configuration.defaultRpcEndpointIndex]
|
|
307
|
+
.networkClientId,
|
|
308
|
+
};
|
|
309
|
+
});
|
|
310
|
+
}, _TokenDetectionController_getCorrectChainIdAndNetworkClientId = function _TokenDetectionController_getCorrectChainIdAndNetworkClientId() {
|
|
334
311
|
const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|
|
335
312
|
const { configuration: { chainId }, } = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
|
|
336
313
|
return {
|
|
@@ -344,14 +321,76 @@ async function _TokenDetectionController_startPolling() {
|
|
|
344
321
|
*
|
|
345
322
|
* @param options - Options for restart token detection.
|
|
346
323
|
* @param options.selectedAddress - the selectedAddress against which to detect for token balances
|
|
347
|
-
* @param options.
|
|
324
|
+
* @param options.chainIds - The chain IDs of the network client to use.
|
|
348
325
|
*/
|
|
349
|
-
async function _TokenDetectionController_restartTokenDetection({ selectedAddress,
|
|
326
|
+
async function _TokenDetectionController_restartTokenDetection({ selectedAddress, chainIds, } = {}) {
|
|
350
327
|
await this.detectTokens({
|
|
351
|
-
|
|
328
|
+
chainIds,
|
|
352
329
|
selectedAddress,
|
|
353
330
|
});
|
|
354
331
|
this.setIntervalLength(DEFAULT_INTERVAL);
|
|
332
|
+
}, _TokenDetectionController_getChainsToDetect = function _TokenDetectionController_getChainsToDetect(clientNetworks, supportedNetworks) {
|
|
333
|
+
const chainsToDetectUsingAccountAPI = [];
|
|
334
|
+
const chainsToDetectUsingRpc = [];
|
|
335
|
+
clientNetworks.forEach(({ chainId, networkClientId }) => {
|
|
336
|
+
if (supportedNetworks?.includes(hexToNumber(chainId))) {
|
|
337
|
+
chainsToDetectUsingAccountAPI.push(chainId);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
chainsToDetectUsingRpc.push({ chainId, networkClientId });
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
return { chainsToDetectUsingRpc, chainsToDetectUsingAccountAPI };
|
|
344
|
+
}, _TokenDetectionController_attemptAccountAPIDetection = async function _TokenDetectionController_attemptAccountAPIDetection(chainsToDetectUsingAccountAPI, addressToDetect, supportedNetworks) {
|
|
345
|
+
return await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_addDetectedTokensViaAPI).call(this, {
|
|
346
|
+
chainIds: chainsToDetectUsingAccountAPI,
|
|
347
|
+
selectedAddress: addressToDetect,
|
|
348
|
+
supportedNetworks,
|
|
349
|
+
});
|
|
350
|
+
}, _TokenDetectionController_addChainsToRpcDetection = function _TokenDetectionController_addChainsToRpcDetection(chainsToDetectUsingRpc, chainsToDetectUsingAccountAPI, clientNetworks) {
|
|
351
|
+
chainsToDetectUsingAccountAPI.forEach((chainId) => {
|
|
352
|
+
const networkEntry = clientNetworks.find((network) => network.chainId === chainId);
|
|
353
|
+
if (networkEntry) {
|
|
354
|
+
chainsToDetectUsingRpc.push({
|
|
355
|
+
chainId: networkEntry.chainId,
|
|
356
|
+
networkClientId: networkEntry.networkClientId,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}, _TokenDetectionController_shouldDetectTokens = function _TokenDetectionController_shouldDetectTokens(chainId) {
|
|
361
|
+
if (!isTokenDetectionSupportedForNetwork(chainId)) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
if (!__classPrivateFieldGet(this, _TokenDetectionController_isDetectionEnabledFromPreferences, "f") &&
|
|
365
|
+
chainId !== ChainId.mainnet) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
const isMainnetDetectionInactive = !__classPrivateFieldGet(this, _TokenDetectionController_isDetectionEnabledFromPreferences, "f") && chainId === ChainId.mainnet;
|
|
369
|
+
if (isMainnetDetectionInactive) {
|
|
370
|
+
__classPrivateFieldSet(this, _TokenDetectionController_tokensChainsCache, __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getConvertedStaticMainnetTokenList).call(this), "f");
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
const { tokensChainsCache } = this.messagingSystem.call('TokenListController:getState');
|
|
374
|
+
__classPrivateFieldSet(this, _TokenDetectionController_tokensChainsCache, tokensChainsCache ?? {}, "f");
|
|
375
|
+
}
|
|
376
|
+
return true;
|
|
377
|
+
}, _TokenDetectionController_detectTokensUsingRpc = async function _TokenDetectionController_detectTokensUsingRpc(chainsToDetectUsingRpc, addressToDetect) {
|
|
378
|
+
for (const { chainId, networkClientId } of chainsToDetectUsingRpc) {
|
|
379
|
+
if (!__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_shouldDetectTokens).call(this, chainId)) {
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
const tokenCandidateSlices = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSlicesOfTokensToDetect).call(this, {
|
|
383
|
+
chainId,
|
|
384
|
+
selectedAddress: addressToDetect,
|
|
385
|
+
});
|
|
386
|
+
const tokenDetectionPromises = tokenCandidateSlices.map((tokensSlice) => __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_addDetectedTokens).call(this, {
|
|
387
|
+
tokensSlice,
|
|
388
|
+
selectedAddress: addressToDetect,
|
|
389
|
+
networkClientId,
|
|
390
|
+
chainId,
|
|
391
|
+
}));
|
|
392
|
+
await Promise.all(tokenDetectionPromises);
|
|
393
|
+
}
|
|
355
394
|
}, _TokenDetectionController_getSlicesOfTokensToDetect = function _TokenDetectionController_getSlicesOfTokensToDetect({ chainId, selectedAddress, }) {
|
|
356
395
|
const { allTokens, allDetectedTokens, allIgnoredTokens } = this.messagingSystem.call('TokensController:getState');
|
|
357
396
|
const [tokensAddresses, detectedTokensAddresses, ignoredTokensAddresses] = [
|
|
@@ -397,68 +436,92 @@ async function _TokenDetectionController_restartTokenDetection({ selectedAddress
|
|
|
397
436
|
* This adds detected tokens from the Accounts API, avoiding the multi-call RPC calls for balances
|
|
398
437
|
* @param options - method arguments
|
|
399
438
|
* @param options.selectedAddress - address to check against
|
|
400
|
-
* @param options.
|
|
401
|
-
* @param options.
|
|
402
|
-
* We will use these these token candidates to determine if a token found from the API is valid to be added on the users wallet.
|
|
403
|
-
* It will also prevent us to adding tokens a user already has
|
|
439
|
+
* @param options.chainIds - array of chainIds to check tokens for
|
|
440
|
+
* @param options.supportedNetworks - array of chainIds to check tokens for
|
|
404
441
|
* @returns a success or failed object
|
|
405
442
|
*/
|
|
406
|
-
async function _TokenDetectionController_addDetectedTokensViaAPI({ selectedAddress,
|
|
443
|
+
async function _TokenDetectionController_addDetectedTokensViaAPI({ selectedAddress, chainIds, supportedNetworks, }) {
|
|
407
444
|
return await safelyExecute(async () => {
|
|
408
|
-
|
|
409
|
-
|
|
445
|
+
// Fetch balances for multiple chain IDs at once
|
|
446
|
+
const tokenBalancesByChain = await __classPrivateFieldGet(this, _TokenDetectionController_accountsAPI, "f")
|
|
447
|
+
.getMultiNetworksBalances(selectedAddress, chainIds, supportedNetworks)
|
|
410
448
|
.catch(() => null);
|
|
411
|
-
if (!
|
|
449
|
+
if (!tokenBalancesByChain ||
|
|
450
|
+
Object.keys(tokenBalancesByChain).length === 0) {
|
|
412
451
|
return { result: 'failed' };
|
|
413
452
|
}
|
|
414
|
-
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
// We need specific data from tokensChainsCache to correctly create a token
|
|
425
|
-
// So even if we have a token that was detected correctly by the API, if its missing data we cannot safely add it.
|
|
426
|
-
if (!__classPrivateFieldGet(this, _TokenDetectionController_tokensChainsCache, "f")[chainId].data[token.address]) {
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
const { decimals, symbol, aggregators, iconUrl, name } = __classPrivateFieldGet(this, _TokenDetectionController_tokensChainsCache, "f")[chainId].data[token.address];
|
|
430
|
-
eventTokensDetails.push(`${symbol} - ${tokenAddress}`);
|
|
431
|
-
tokensWithBalance.push({
|
|
432
|
-
address: tokenAddress,
|
|
433
|
-
decimals,
|
|
434
|
-
symbol,
|
|
435
|
-
aggregators,
|
|
436
|
-
image: iconUrl,
|
|
437
|
-
isERC721: false,
|
|
438
|
-
name,
|
|
439
|
-
});
|
|
440
|
-
});
|
|
441
|
-
if (tokensWithBalance.length) {
|
|
442
|
-
__classPrivateFieldGet(this, _TokenDetectionController_trackMetaMetricsEvent, "f").call(this, {
|
|
443
|
-
event: 'Token Detected',
|
|
444
|
-
category: 'Wallet',
|
|
445
|
-
properties: {
|
|
446
|
-
tokens: eventTokensDetails,
|
|
447
|
-
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
448
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
449
|
-
token_standard: ERC20,
|
|
450
|
-
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
451
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
452
|
-
asset_type: ASSET_TYPES.TOKEN,
|
|
453
|
-
},
|
|
454
|
-
});
|
|
455
|
-
await this.messagingSystem.call('TokensController:addDetectedTokens', tokensWithBalance, {
|
|
456
|
-
selectedAddress,
|
|
453
|
+
// Process each chain ID individually
|
|
454
|
+
for (const chainId of chainIds) {
|
|
455
|
+
const isTokenDetectionInactiveInMainnet = !__classPrivateFieldGet(this, _TokenDetectionController_isDetectionEnabledFromPreferences, "f") &&
|
|
456
|
+
chainId === ChainId.mainnet;
|
|
457
|
+
const { tokensChainsCache } = this.messagingSystem.call('TokenListController:getState');
|
|
458
|
+
__classPrivateFieldSet(this, _TokenDetectionController_tokensChainsCache, isTokenDetectionInactiveInMainnet
|
|
459
|
+
? __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getConvertedStaticMainnetTokenList).call(this)
|
|
460
|
+
: tokensChainsCache ?? {}, "f");
|
|
461
|
+
// Generate token candidates based on chainId and selectedAddress
|
|
462
|
+
const tokenCandidateSlices = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSlicesOfTokensToDetect).call(this, {
|
|
457
463
|
chainId,
|
|
464
|
+
selectedAddress,
|
|
458
465
|
});
|
|
466
|
+
// Filter balances for the current chainId
|
|
467
|
+
const tokenBalances = tokenBalancesByChain.filter((balance) => balance.chainId === hexToNumber(chainId));
|
|
468
|
+
if (!tokenBalances || tokenBalances.length === 0) {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
// Use helper function to filter tokens with balance for this chainId
|
|
472
|
+
const { tokensWithBalance, eventTokensDetails } = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_filterAndBuildTokensWithBalance).call(this, tokenCandidateSlices, tokenBalances, chainId);
|
|
473
|
+
if (tokensWithBalance.length) {
|
|
474
|
+
__classPrivateFieldGet(this, _TokenDetectionController_trackMetaMetricsEvent, "f").call(this, {
|
|
475
|
+
event: 'Token Detected',
|
|
476
|
+
category: 'Wallet',
|
|
477
|
+
properties: {
|
|
478
|
+
tokens: eventTokensDetails,
|
|
479
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
480
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
481
|
+
token_standard: ERC20,
|
|
482
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
483
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
484
|
+
asset_type: ASSET_TYPES.TOKEN,
|
|
485
|
+
},
|
|
486
|
+
});
|
|
487
|
+
await this.messagingSystem.call('TokensController:addDetectedTokens', tokensWithBalance, {
|
|
488
|
+
selectedAddress,
|
|
489
|
+
chainId,
|
|
490
|
+
});
|
|
491
|
+
}
|
|
459
492
|
}
|
|
460
493
|
return { result: 'success' };
|
|
461
494
|
});
|
|
495
|
+
}, _TokenDetectionController_filterAndBuildTokensWithBalance = function _TokenDetectionController_filterAndBuildTokensWithBalance(tokenCandidateSlices, tokenBalances, chainId) {
|
|
496
|
+
const tokensWithBalance = [];
|
|
497
|
+
const eventTokensDetails = [];
|
|
498
|
+
const tokenCandidateSet = new Set(tokenCandidateSlices.flat());
|
|
499
|
+
tokenBalances?.forEach((token) => {
|
|
500
|
+
const tokenAddress = token.address;
|
|
501
|
+
// Make sure the token to add is in our candidate list
|
|
502
|
+
if (!tokenCandidateSet.has(tokenAddress)) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
// Retrieve token data from cache to safely add it
|
|
506
|
+
const tokenData = __classPrivateFieldGet(this, _TokenDetectionController_tokensChainsCache, "f")[chainId]?.data[tokenAddress];
|
|
507
|
+
// We need specific data from tokensChainsCache to correctly create a token
|
|
508
|
+
// So even if we have a token that was detected correctly by the API, if its missing data we cannot safely add it.
|
|
509
|
+
if (!tokenData) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
const { decimals, symbol, aggregators, iconUrl, name } = tokenData;
|
|
513
|
+
eventTokensDetails.push(`${symbol} - ${tokenAddress}`);
|
|
514
|
+
tokensWithBalance.push({
|
|
515
|
+
address: tokenAddress,
|
|
516
|
+
decimals,
|
|
517
|
+
symbol,
|
|
518
|
+
aggregators,
|
|
519
|
+
image: iconUrl,
|
|
520
|
+
isERC721: false,
|
|
521
|
+
name,
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
return { tokensWithBalance, eventTokensDetails };
|
|
462
525
|
}, _TokenDetectionController_addDetectedTokens = async function _TokenDetectionController_addDetectedTokens({ tokensSlice, selectedAddress, networkClientId, chainId, }) {
|
|
463
526
|
await safelyExecute(async () => {
|
|
464
527
|
const balances = await __classPrivateFieldGet(this, _TokenDetectionController_getBalancesInSingleCall, "f").call(this, selectedAddress, tokensSlice, networkClientId);
|