@metamask/assets-controllers 41.0.0 → 43.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 +31 -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/NftController.cjs +8 -0
- package/dist/NftController.cjs.map +1 -1
- package/dist/NftController.d.cts +4 -0
- package/dist/NftController.d.cts.map +1 -1
- package/dist/NftController.d.mts +4 -0
- package/dist/NftController.d.mts.map +1 -1
- package/dist/NftController.mjs +8 -0
- package/dist/NftController.mjs.map +1 -1
- package/dist/TokenBalancesController.cjs +8 -0
- package/dist/TokenBalancesController.cjs.map +1 -1
- package/dist/TokenBalancesController.d.cts +4 -0
- package/dist/TokenBalancesController.d.cts.map +1 -1
- package/dist/TokenBalancesController.d.mts +4 -0
- package/dist/TokenBalancesController.d.mts.map +1 -1
- package/dist/TokenBalancesController.mjs +8 -0
- package/dist/TokenBalancesController.mjs.map +1 -1
- package/dist/TokenDetectionController.cjs +196 -129
- package/dist/TokenDetectionController.cjs.map +1 -1
- package/dist/TokenDetectionController.d.cts +23 -12
- package/dist/TokenDetectionController.d.cts.map +1 -1
- package/dist/TokenDetectionController.d.mts +23 -12
- package/dist/TokenDetectionController.d.mts.map +1 -1
- package/dist/TokenDetectionController.mjs +195 -129
- 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.cjs +43 -13
- package/dist/TokenRatesController.cjs.map +1 -1
- package/dist/TokenRatesController.d.cts +12 -8
- package/dist/TokenRatesController.d.cts.map +1 -1
- package/dist/TokenRatesController.d.mts +12 -8
- package/dist/TokenRatesController.d.mts.map +1 -1
- package/dist/TokenRatesController.mjs +43 -13
- package/dist/TokenRatesController.mjs.map +1 -1
- package/dist/TokensController.cjs +15 -4
- package/dist/TokensController.cjs.map +1 -1
- package/dist/TokensController.d.cts +4 -0
- package/dist/TokensController.d.cts.map +1 -1
- package/dist/TokensController.d.mts +4 -0
- package/dist/TokensController.d.mts.map +1 -1
- package/dist/TokensController.mjs +15 -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/dist/multi-chain-accounts-service/multi-chain-accounts.cjs +7 -2
- package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts +3 -2
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts +3 -2
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs +7 -2
- package/dist/multi-chain-accounts-service/multi-chain-accounts.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']);
|
|
@@ -73,8 +73,9 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
73
73
|
* @param options.getBalancesInSingleCall - Gets the balances of a list of tokens for the given address.
|
|
74
74
|
* @param options.trackMetaMetricsEvent - Sets options for MetaMetrics event tracking.
|
|
75
75
|
* @param options.useAccountsAPI - Feature Switch for using the accounts API when detecting tokens (default: true)
|
|
76
|
+
* @param options.platform - Indicates whether the platform is extension or mobile
|
|
76
77
|
*/
|
|
77
|
-
constructor({ interval = DEFAULT_INTERVAL, disabled = true, getBalancesInSingleCall, trackMetaMetricsEvent, messenger, useAccountsAPI = true, }) {
|
|
78
|
+
constructor({ interval = DEFAULT_INTERVAL, disabled = true, getBalancesInSingleCall, trackMetaMetricsEvent, messenger, useAccountsAPI = true, platform, }) {
|
|
78
79
|
super({
|
|
79
80
|
name: controllerName,
|
|
80
81
|
messenger,
|
|
@@ -95,6 +96,7 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
95
96
|
_TokenDetectionController_accountsAPI.set(this, {
|
|
96
97
|
isAccountsAPIEnabled: true,
|
|
97
98
|
supportedNetworksCache: null,
|
|
99
|
+
platform: '',
|
|
98
100
|
async getSupportedNetworks() {
|
|
99
101
|
/* istanbul ignore next */
|
|
100
102
|
if (!this.isAccountsAPIEnabled) {
|
|
@@ -108,19 +110,16 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
108
110
|
this.supportedNetworksCache = result;
|
|
109
111
|
return result;
|
|
110
112
|
},
|
|
111
|
-
async
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const chainIdNumber = hexToNumber(chainId);
|
|
116
|
-
const supportedNetworks = await this.getSupportedNetworks();
|
|
117
|
-
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))) {
|
|
118
117
|
const supportedNetworksErrStr = (supportedNetworks ?? []).toString();
|
|
119
|
-
throw new Error(`Unsupported Network: supported networks ${supportedNetworksErrStr},
|
|
118
|
+
throw new Error(`Unsupported Network: supported networks ${supportedNetworksErrStr}, requested networks: ${chainIdNumbers.toString()}`);
|
|
120
119
|
}
|
|
121
120
|
const result = await fetchMultiChainBalances(address, {
|
|
122
|
-
networks:
|
|
123
|
-
});
|
|
121
|
+
networks: chainIdNumbers,
|
|
122
|
+
}, this.platform);
|
|
124
123
|
return result.balances;
|
|
125
124
|
},
|
|
126
125
|
});
|
|
@@ -139,6 +138,7 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
139
138
|
const { isUnlocked } = this.messagingSystem.call('KeyringController:getState');
|
|
140
139
|
__classPrivateFieldSet(this, _TokenDetectionController_isUnlocked, isUnlocked, "f");
|
|
141
140
|
__classPrivateFieldGet(this, _TokenDetectionController_accountsAPI, "f").isAccountsAPIEnabled = useAccountsAPI;
|
|
141
|
+
__classPrivateFieldGet(this, _TokenDetectionController_accountsAPI, "f").platform = platform;
|
|
142
142
|
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_registerEventListeners).call(this);
|
|
143
143
|
}
|
|
144
144
|
/**
|
|
@@ -174,12 +174,12 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
174
174
|
this.disable();
|
|
175
175
|
__classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_stopPolling).call(this);
|
|
176
176
|
}
|
|
177
|
-
async _executePoll({
|
|
177
|
+
async _executePoll({ chainIds, address, }) {
|
|
178
178
|
if (!this.isActive) {
|
|
179
179
|
return;
|
|
180
180
|
}
|
|
181
181
|
await this.detectTokens({
|
|
182
|
-
|
|
182
|
+
chainIds,
|
|
183
183
|
selectedAddress: address,
|
|
184
184
|
});
|
|
185
185
|
}
|
|
@@ -188,51 +188,35 @@ export class TokenDetectionController extends StaticIntervalPollingController()
|
|
|
188
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.
|
|
189
189
|
*
|
|
190
190
|
* @param options - Options for token detection.
|
|
191
|
-
* @param options.
|
|
191
|
+
* @param options.chainIds - The chain IDs of the network client to use.
|
|
192
192
|
* @param options.selectedAddress - the selectedAddress against which to detect for token balances.
|
|
193
193
|
*/
|
|
194
|
-
async detectTokens({
|
|
194
|
+
async detectTokens({ chainIds, selectedAddress, } = {}) {
|
|
195
195
|
if (!this.isActive) {
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
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();
|
|
204
203
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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);
|
|
208
215
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
__classPrivateFieldSet(this, _TokenDetectionController_tokensChainsCache, isTokenDetectionInactiveInMainnet
|
|
213
|
-
? __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getConvertedStaticMainnetTokenList).call(this)
|
|
214
|
-
: tokensChainsCache ?? {}, "f");
|
|
215
|
-
const tokenCandidateSlices = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getSlicesOfTokensToDetect).call(this, {
|
|
216
|
-
chainId: chainIdAgainstWhichToDetect,
|
|
217
|
-
selectedAddress: addressAgainstWhichToDetect,
|
|
218
|
-
});
|
|
219
|
-
// Attempt Accounts API Detection
|
|
220
|
-
const accountAPIResult = await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_addDetectedTokensViaAPI).call(this, {
|
|
221
|
-
chainId: chainIdAgainstWhichToDetect,
|
|
222
|
-
selectedAddress: addressAgainstWhichToDetect,
|
|
223
|
-
tokenCandidateSlices,
|
|
224
|
-
});
|
|
225
|
-
if (accountAPIResult?.result === 'success') {
|
|
226
|
-
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);
|
|
227
219
|
}
|
|
228
|
-
// Attempt RPC Detection
|
|
229
|
-
const tokenDetectionPromises = tokenCandidateSlices.map((tokensSlice) => __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_addDetectedTokens).call(this, {
|
|
230
|
-
tokensSlice,
|
|
231
|
-
selectedAddress: addressAgainstWhichToDetect,
|
|
232
|
-
networkClientId: networkClientIdAgainstWhichToDetect,
|
|
233
|
-
chainId: chainIdAgainstWhichToDetect,
|
|
234
|
-
}));
|
|
235
|
-
await Promise.all(tokenDetectionPromises);
|
|
236
220
|
}
|
|
237
221
|
}
|
|
238
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() {
|
|
@@ -280,20 +264,6 @@ _TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_
|
|
|
280
264
|
});
|
|
281
265
|
}
|
|
282
266
|
});
|
|
283
|
-
this.messagingSystem.subscribe('NetworkController:networkDidChange',
|
|
284
|
-
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
285
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
286
|
-
async ({ selectedNetworkClientId }) => {
|
|
287
|
-
const isNetworkClientIdChanged = __classPrivateFieldGet(this, _TokenDetectionController_networkClientId, "f") !== selectedNetworkClientId;
|
|
288
|
-
const { chainId: newChainId } = __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_getCorrectChainIdAndNetworkClientId).call(this, selectedNetworkClientId);
|
|
289
|
-
__classPrivateFieldSet(this, _TokenDetectionController_isDetectionEnabledForNetwork, isTokenDetectionSupportedForNetwork(newChainId), "f");
|
|
290
|
-
if (isNetworkClientIdChanged && __classPrivateFieldGet(this, _TokenDetectionController_isDetectionEnabledForNetwork, "f")) {
|
|
291
|
-
__classPrivateFieldSet(this, _TokenDetectionController_networkClientId, selectedNetworkClientId, "f");
|
|
292
|
-
await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_restartTokenDetection).call(this, {
|
|
293
|
-
networkClientId: __classPrivateFieldGet(this, _TokenDetectionController_networkClientId, "f"),
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
267
|
}, _TokenDetectionController_stopPolling = function _TokenDetectionController_stopPolling() {
|
|
298
268
|
if (__classPrivateFieldGet(this, _TokenDetectionController_intervalId, "f")) {
|
|
299
269
|
clearInterval(__classPrivateFieldGet(this, _TokenDetectionController_intervalId, "f"));
|
|
@@ -318,16 +288,26 @@ async function _TokenDetectionController_startPolling() {
|
|
|
318
288
|
const cleanTokensChainsCache = mapChainIdWithTokenListMap(tokensChainsCache);
|
|
319
289
|
const isEqualValues = isEqual(cleanTokensChainsCache, cleanPreviousTokensChainsCache);
|
|
320
290
|
return isEqualValues;
|
|
321
|
-
},
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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
|
+
];
|
|
330
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() {
|
|
331
311
|
const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|
|
332
312
|
const { configuration: { chainId }, } = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
|
|
333
313
|
return {
|
|
@@ -341,14 +321,76 @@ async function _TokenDetectionController_startPolling() {
|
|
|
341
321
|
*
|
|
342
322
|
* @param options - Options for restart token detection.
|
|
343
323
|
* @param options.selectedAddress - the selectedAddress against which to detect for token balances
|
|
344
|
-
* @param options.
|
|
324
|
+
* @param options.chainIds - The chain IDs of the network client to use.
|
|
345
325
|
*/
|
|
346
|
-
async function _TokenDetectionController_restartTokenDetection({ selectedAddress,
|
|
326
|
+
async function _TokenDetectionController_restartTokenDetection({ selectedAddress, chainIds, } = {}) {
|
|
347
327
|
await this.detectTokens({
|
|
348
|
-
|
|
328
|
+
chainIds,
|
|
349
329
|
selectedAddress,
|
|
350
330
|
});
|
|
351
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
|
+
}
|
|
352
394
|
}, _TokenDetectionController_getSlicesOfTokensToDetect = function _TokenDetectionController_getSlicesOfTokensToDetect({ chainId, selectedAddress, }) {
|
|
353
395
|
const { allTokens, allDetectedTokens, allIgnoredTokens } = this.messagingSystem.call('TokensController:getState');
|
|
354
396
|
const [tokensAddresses, detectedTokensAddresses, ignoredTokensAddresses] = [
|
|
@@ -394,68 +436,92 @@ async function _TokenDetectionController_restartTokenDetection({ selectedAddress
|
|
|
394
436
|
* This adds detected tokens from the Accounts API, avoiding the multi-call RPC calls for balances
|
|
395
437
|
* @param options - method arguments
|
|
396
438
|
* @param options.selectedAddress - address to check against
|
|
397
|
-
* @param options.
|
|
398
|
-
* @param options.
|
|
399
|
-
* 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.
|
|
400
|
-
* 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
|
|
401
441
|
* @returns a success or failed object
|
|
402
442
|
*/
|
|
403
|
-
async function _TokenDetectionController_addDetectedTokensViaAPI({ selectedAddress,
|
|
443
|
+
async function _TokenDetectionController_addDetectedTokensViaAPI({ selectedAddress, chainIds, supportedNetworks, }) {
|
|
404
444
|
return await safelyExecute(async () => {
|
|
405
|
-
|
|
406
|
-
|
|
445
|
+
// Fetch balances for multiple chain IDs at once
|
|
446
|
+
const tokenBalancesByChain = await __classPrivateFieldGet(this, _TokenDetectionController_accountsAPI, "f")
|
|
447
|
+
.getMultiNetworksBalances(selectedAddress, chainIds, supportedNetworks)
|
|
407
448
|
.catch(() => null);
|
|
408
|
-
if (!
|
|
449
|
+
if (!tokenBalancesByChain ||
|
|
450
|
+
Object.keys(tokenBalancesByChain).length === 0) {
|
|
409
451
|
return { result: 'failed' };
|
|
410
452
|
}
|
|
411
|
-
|
|
412
|
-
const
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
// We need specific data from tokensChainsCache to correctly create a token
|
|
422
|
-
// So even if we have a token that was detected correctly by the API, if its missing data we cannot safely add it.
|
|
423
|
-
if (!__classPrivateFieldGet(this, _TokenDetectionController_tokensChainsCache, "f")[chainId].data[token.address]) {
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
const { decimals, symbol, aggregators, iconUrl, name } = __classPrivateFieldGet(this, _TokenDetectionController_tokensChainsCache, "f")[chainId].data[token.address];
|
|
427
|
-
eventTokensDetails.push(`${symbol} - ${tokenAddress}`);
|
|
428
|
-
tokensWithBalance.push({
|
|
429
|
-
address: tokenAddress,
|
|
430
|
-
decimals,
|
|
431
|
-
symbol,
|
|
432
|
-
aggregators,
|
|
433
|
-
image: iconUrl,
|
|
434
|
-
isERC721: false,
|
|
435
|
-
name,
|
|
436
|
-
});
|
|
437
|
-
});
|
|
438
|
-
if (tokensWithBalance.length) {
|
|
439
|
-
__classPrivateFieldGet(this, _TokenDetectionController_trackMetaMetricsEvent, "f").call(this, {
|
|
440
|
-
event: 'Token Detected',
|
|
441
|
-
category: 'Wallet',
|
|
442
|
-
properties: {
|
|
443
|
-
tokens: eventTokensDetails,
|
|
444
|
-
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
445
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
446
|
-
token_standard: ERC20,
|
|
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
|
-
asset_type: ASSET_TYPES.TOKEN,
|
|
450
|
-
},
|
|
451
|
-
});
|
|
452
|
-
await this.messagingSystem.call('TokensController:addDetectedTokens', tokensWithBalance, {
|
|
453
|
-
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, {
|
|
454
463
|
chainId,
|
|
464
|
+
selectedAddress,
|
|
455
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
|
+
}
|
|
456
492
|
}
|
|
457
493
|
return { result: 'success' };
|
|
458
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 };
|
|
459
525
|
}, _TokenDetectionController_addDetectedTokens = async function _TokenDetectionController_addDetectedTokens({ tokensSlice, selectedAddress, networkClientId, chainId, }) {
|
|
460
526
|
await safelyExecute(async () => {
|
|
461
527
|
const balances = await __classPrivateFieldGet(this, _TokenDetectionController_getBalancesInSingleCall, "f").call(this, selectedAddress, tokensSlice, networkClientId);
|