@metamask-previews/assets-controllers 58.0.0-preview-3d7a30d → 58.0.0-preview-d11c4815

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 CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Changed
11
+
12
+ - **UPDATE:** Refactor `TokenRatesController` to support processing multiple chains simultaneously. The controller now accepts an array of chain IDs and tickers instead of a single value, streamlining the polling process by iterating over all chains in one loop ([#5645](https://github.com/MetaMask/core/pull/5645))
13
+
14
+ ### Removed
15
+
16
+ - **BREAKING:** Eliminate legacy network dependency handling in `TokenRatesController`. Clients must now pass an array (rather than a single object) for chain IDs and tickers. This change may require updates on the client side to align with the new array-based input ([#5645](https://github.com/MetaMask/core/pull/5645))
17
+
10
18
  ## [58.0.0]
11
19
 
12
20
  ### Added
@@ -55,9 +63,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
55
63
  - **BREAKING:** Remove deprecated state fields scoped to the current chain ([#5310](https://github.com/MetaMask/core/pull/5310))
56
64
  - This change removes the following state fields from the following controllers:
57
65
  - `TokensControllerState`
58
- - `detectedTokens` (replaced by `detectedTokensByChainId`)
59
- - `ignoredTokens` (replaced by `ignoredTokensByChainId`)
60
- - `tokens` (replaced by `tokensByChainId`)
66
+ - `detectedTokens` (replaced by `allDetectedTokens`)
67
+ - `ignoredTokens` (replaced by `allIgnoredTokens`)
68
+ - `tokens` (replaced by `allTokens`)
61
69
  - `TokenListControllerState`
62
70
  - `tokenList` (replaced by `tokensChainsCache`)
63
71
  - `AccountTrackerControllerState`
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  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");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _TokenRatesController_instances, _TokenRatesController_handle, _TokenRatesController_pollState, _TokenRatesController_tokenPricesService, _TokenRatesController_inProcessExchangeRateUpdates, _TokenRatesController_selectedAccountId, _TokenRatesController_disabled, _TokenRatesController_chainId, _TokenRatesController_ticker, _TokenRatesController_interval, _TokenRatesController_allTokens, _TokenRatesController_allDetectedTokens, _TokenRatesController_subscribeToTokensStateChange, _TokenRatesController_subscribeToNetworkStateChange, _TokenRatesController_getTokenAddresses, _TokenRatesController_getSelectedAccount, _TokenRatesController_getChainIdAndTicker, _TokenRatesController_getTokensControllerState, _TokenRatesController_stopPoll, _TokenRatesController_poll, _TokenRatesController_fetchAndMapExchangeRates, _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency, _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency;
13
+ var _TokenRatesController_instances, _TokenRatesController_handle, _TokenRatesController_pollState, _TokenRatesController_tokenPricesService, _TokenRatesController_inProcessExchangeRateUpdates, _TokenRatesController_disabled, _TokenRatesController_interval, _TokenRatesController_allTokens, _TokenRatesController_allDetectedTokens, _TokenRatesController_subscribeToTokensStateChange, _TokenRatesController_subscribeToNetworkStateChange, _TokenRatesController_getTokenAddresses, _TokenRatesController_getTokensControllerState, _TokenRatesController_stopPoll, _TokenRatesController_poll, _TokenRatesController_fetchAndMapExchangeRates, _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency, _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.TokenRatesController = exports.getDefaultTokenRatesControllerState = exports.controllerName = void 0;
16
16
  const controller_utils_1 = require("@metamask/controller-utils");
@@ -96,10 +96,7 @@ class TokenRatesController extends (0, polling_controller_1.StaticIntervalPollin
96
96
  _TokenRatesController_pollState.set(this, PollState.Inactive);
97
97
  _TokenRatesController_tokenPricesService.set(this, void 0);
98
98
  _TokenRatesController_inProcessExchangeRateUpdates.set(this, {});
99
- _TokenRatesController_selectedAccountId.set(this, void 0);
100
99
  _TokenRatesController_disabled.set(this, void 0);
101
- _TokenRatesController_chainId.set(this, void 0);
102
- _TokenRatesController_ticker.set(this, void 0);
103
100
  _TokenRatesController_interval.set(this, void 0);
104
101
  _TokenRatesController_allTokens.set(this, void 0);
105
102
  _TokenRatesController_allDetectedTokens.set(this, void 0);
@@ -107,10 +104,6 @@ class TokenRatesController extends (0, polling_controller_1.StaticIntervalPollin
107
104
  __classPrivateFieldSet(this, _TokenRatesController_tokenPricesService, tokenPricesService, "f");
108
105
  __classPrivateFieldSet(this, _TokenRatesController_disabled, disabled, "f");
109
106
  __classPrivateFieldSet(this, _TokenRatesController_interval, interval, "f");
110
- const { chainId: currentChainId, ticker: currentTicker } = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getChainIdAndTicker).call(this);
111
- __classPrivateFieldSet(this, _TokenRatesController_chainId, currentChainId, "f");
112
- __classPrivateFieldSet(this, _TokenRatesController_ticker, currentTicker, "f");
113
- __classPrivateFieldSet(this, _TokenRatesController_selectedAccountId, __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getSelectedAccount).call(this).id, "f");
114
107
  const { allTokens, allDetectedTokens } = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getTokensControllerState).call(this);
115
108
  __classPrivateFieldSet(this, _TokenRatesController_allTokens, allTokens, "f");
116
109
  __classPrivateFieldSet(this, _TokenRatesController_allDetectedTokens, allDetectedTokens, "f");
@@ -131,11 +124,14 @@ class TokenRatesController extends (0, polling_controller_1.StaticIntervalPollin
131
124
  }
132
125
  /**
133
126
  * Start (or restart) polling.
127
+ *
128
+ * @param chainId - The chain ID.
129
+ * @param nativeCurrency - The native currency.
134
130
  */
135
- async start() {
131
+ async start(chainId, nativeCurrency) {
136
132
  __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_stopPoll).call(this);
137
133
  __classPrivateFieldSet(this, _TokenRatesController_pollState, PollState.Active, "f");
138
- await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this);
134
+ await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this, chainId, nativeCurrency);
139
135
  }
140
136
  /**
141
137
  * Stop polling.
@@ -146,83 +142,91 @@ class TokenRatesController extends (0, polling_controller_1.StaticIntervalPollin
146
142
  }
147
143
  /**
148
144
  * Updates exchange rates for all tokens.
145
+ *
146
+ * @param chainIdAndNativeCurrency - The chain ID and native currency.
149
147
  */
150
- async updateExchangeRates() {
151
- await this.updateExchangeRatesByChainId({
152
- chainId: __classPrivateFieldGet(this, _TokenRatesController_chainId, "f"),
153
- nativeCurrency: __classPrivateFieldGet(this, _TokenRatesController_ticker, "f"),
154
- });
148
+ async updateExchangeRates(chainIdAndNativeCurrency) {
149
+ await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);
155
150
  }
156
151
  /**
157
152
  * Updates exchange rates for all tokens.
158
153
  *
159
- * @param options - The options to fetch exchange rates.
160
- * @param options.chainId - The chain ID.
161
- * @param options.nativeCurrency - The ticker for the chain.
154
+ * @param chainIds - The chain IDs.
155
+ * @returns A promise that resolves when all chain updates complete.
156
+ */
157
+ /**
158
+ * Updates exchange rates for all tokens.
159
+ *
160
+ * @param chainIdAndNativeCurrency - The chain ID and native currency.
162
161
  */
163
- async updateExchangeRatesByChainId({ chainId, nativeCurrency, }) {
162
+ async updateExchangeRatesByChainId(chainIdAndNativeCurrency) {
164
163
  if (__classPrivateFieldGet(this, _TokenRatesController_disabled, "f")) {
165
164
  return;
166
165
  }
167
- const tokenAddresses = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getTokenAddresses).call(this, chainId);
168
- // Key dependencies that will trigger a new request instead of aborting:
169
- // - chainId - different chains require a new request
170
- // - nativeCurrency - changing native currency requires fetching different rates
171
- // - tokenAddress length - if we have detected any new tokens, we will need to make a new request for the rates
172
- const updateKey = `${chainId}:${nativeCurrency}:${tokenAddresses.length}`;
173
- if (updateKey in __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")) {
174
- // This prevents redundant updates
175
- // This promise is resolved after the in-progress update has finished,
176
- // and state has been updated.
177
- await __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
178
- return;
179
- }
180
- const { promise: inProgressUpdate, resolve: updateSucceeded, reject: updateFailed, } = (0, utils_1.createDeferredPromise)({ suppressUnhandledRejection: true });
181
- __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey] = inProgressUpdate;
182
- try {
183
- const contractInformations = await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRates).call(this, {
184
- tokenAddresses,
185
- chainId,
186
- nativeCurrency,
187
- });
188
- const marketData = {
189
- [chainId]: {
190
- ...(contractInformations ?? {}),
191
- },
192
- };
166
+ // Create a promise for each chainId to fetch exchange rates.
167
+ const updatePromises = chainIdAndNativeCurrency.map(async ({ chainId, nativeCurrency }) => {
168
+ const tokenAddresses = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getTokenAddresses).call(this, chainId);
169
+ // Build a unique key based on chainId, nativeCurrency, and the number of token addresses.
170
+ const updateKey = `${chainId}:${nativeCurrency}:${tokenAddresses.length}`;
171
+ if (updateKey in __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")) {
172
+ // Await any ongoing update to avoid redundant work.
173
+ await __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
174
+ return null;
175
+ }
176
+ // Create a deferred promise to track this update.
177
+ const { promise: inProgressUpdate, resolve: updateSucceeded, reject: updateFailed, } = (0, utils_1.createDeferredPromise)({ suppressUnhandledRejection: true });
178
+ __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey] = inProgressUpdate;
179
+ try {
180
+ const contractInformations = await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRates).call(this, {
181
+ tokenAddresses,
182
+ chainId,
183
+ nativeCurrency,
184
+ });
185
+ // Each promise returns an object with the market data for the chain.
186
+ const marketData = {
187
+ [chainId]: {
188
+ ...(contractInformations ?? {}),
189
+ },
190
+ };
191
+ updateSucceeded();
192
+ return marketData;
193
+ }
194
+ catch (error) {
195
+ updateFailed(error);
196
+ throw error;
197
+ }
198
+ finally {
199
+ // Cleanup the tracking for this update.
200
+ delete __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
201
+ }
202
+ });
203
+ // Wait for all update promises to settle.
204
+ const results = await Promise.allSettled(updatePromises);
205
+ // Merge all successful market data updates into one object.
206
+ const combinedMarketData = results.reduce((acc, result) => {
207
+ if (result.status === 'fulfilled' && result.value) {
208
+ acc = { ...acc, ...result.value };
209
+ }
210
+ return acc;
211
+ }, {});
212
+ // Call this.update only once with the combined market data to reduce the number of state changes and re-renders
213
+ if (Object.keys(combinedMarketData).length > 0) {
193
214
  this.update((state) => {
194
215
  state.marketData = {
195
216
  ...state.marketData,
196
- ...marketData,
217
+ ...combinedMarketData,
197
218
  };
198
219
  });
199
- updateSucceeded();
200
- }
201
- catch (error) {
202
- updateFailed(error);
203
- throw error;
204
- }
205
- finally {
206
- delete __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
207
220
  }
208
221
  }
209
222
  /**
210
223
  * Updates token rates for the given networkClientId
211
224
  *
212
225
  * @param input - The input for the poll.
213
- * @param input.chainId - The chain id to poll token rates on.
226
+ * @param input.chainIdAndNativeCurrency - The chain ids and native currencies to poll token rates on.
214
227
  */
215
- async _executePoll({ chainId }) {
216
- const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
217
- const networkConfiguration = networkConfigurationsByChainId[chainId];
218
- if (!networkConfiguration) {
219
- console.error(`TokenRatesController: No network configuration found for chainId ${chainId}`);
220
- return;
221
- }
222
- await this.updateExchangeRatesByChainId({
223
- chainId,
224
- nativeCurrency: networkConfiguration.nativeCurrency,
225
- });
228
+ async _executePoll({ chainIdAndNativeCurrency, }) {
229
+ await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);
226
230
  }
227
231
  /**
228
232
  * Reset the controller state to the default state.
@@ -234,7 +238,7 @@ class TokenRatesController extends (0, polling_controller_1.StaticIntervalPollin
234
238
  }
235
239
  }
236
240
  exports.TokenRatesController = TokenRatesController;
237
- _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState = new WeakMap(), _TokenRatesController_tokenPricesService = new WeakMap(), _TokenRatesController_inProcessExchangeRateUpdates = new WeakMap(), _TokenRatesController_selectedAccountId = new WeakMap(), _TokenRatesController_disabled = new WeakMap(), _TokenRatesController_chainId = new WeakMap(), _TokenRatesController_ticker = new WeakMap(), _TokenRatesController_interval = new WeakMap(), _TokenRatesController_allTokens = new WeakMap(), _TokenRatesController_allDetectedTokens = new WeakMap(), _TokenRatesController_instances = new WeakSet(), _TokenRatesController_subscribeToTokensStateChange = function _TokenRatesController_subscribeToTokensStateChange() {
241
+ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState = new WeakMap(), _TokenRatesController_tokenPricesService = new WeakMap(), _TokenRatesController_inProcessExchangeRateUpdates = new WeakMap(), _TokenRatesController_disabled = new WeakMap(), _TokenRatesController_interval = new WeakMap(), _TokenRatesController_allTokens = new WeakMap(), _TokenRatesController_allDetectedTokens = new WeakMap(), _TokenRatesController_instances = new WeakSet(), _TokenRatesController_subscribeToTokensStateChange = function _TokenRatesController_subscribeToTokensStateChange() {
238
242
  this.messagingSystem.subscribe('TokensController:stateChange',
239
243
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
240
244
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
@@ -242,6 +246,7 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
242
246
  if (__classPrivateFieldGet(this, _TokenRatesController_disabled, "f")) {
243
247
  return;
244
248
  }
249
+ const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
245
250
  const chainIds = [
246
251
  ...new Set([
247
252
  ...Object.keys(allTokens),
@@ -252,16 +257,13 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
252
257
  !(0, lodash_1.isEqual)(__classPrivateFieldGet(this, _TokenRatesController_allDetectedTokens, "f")[chainId], allDetectedTokens[chainId]));
253
258
  __classPrivateFieldSet(this, _TokenRatesController_allTokens, allTokens, "f");
254
259
  __classPrivateFieldSet(this, _TokenRatesController_allDetectedTokens, allDetectedTokens, "f");
255
- const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
256
- await Promise.allSettled(chainIdsToUpdate.map(async (chainId) => {
257
- const nativeCurrency = networkConfigurationsByChainId[chainId]?.nativeCurrency;
258
- if (nativeCurrency) {
259
- await this.updateExchangeRatesByChainId({
260
- chainId: chainId,
261
- nativeCurrency,
262
- });
263
- }
264
- }));
260
+ const chainIdAndNativeCurrency = chainIdsToUpdate.map((chainId) => {
261
+ return {
262
+ chainId: chainId,
263
+ nativeCurrency: networkConfigurationsByChainId[chainId]?.nativeCurrency,
264
+ };
265
+ });
266
+ await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);
265
267
  }, ({ allTokens, allDetectedTokens }) => {
266
268
  return { allTokens, allDetectedTokens };
267
269
  });
@@ -269,14 +271,15 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
269
271
  this.messagingSystem.subscribe('NetworkController:stateChange',
270
272
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
271
273
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
272
- async ({ selectedNetworkClientId }, patches) => {
273
- const { configuration: { chainId, ticker }, } = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
274
- if (__classPrivateFieldGet(this, _TokenRatesController_chainId, "f") !== chainId || __classPrivateFieldGet(this, _TokenRatesController_ticker, "f") !== ticker) {
275
- __classPrivateFieldSet(this, _TokenRatesController_chainId, chainId, "f");
276
- __classPrivateFieldSet(this, _TokenRatesController_ticker, ticker, "f");
277
- if (__classPrivateFieldGet(this, _TokenRatesController_pollState, "f") === PollState.Active) {
278
- await this.updateExchangeRates();
279
- }
274
+ async ({ networkConfigurationsByChainId }, patches) => {
275
+ const chainIdAndNativeCurrency = Object.values(networkConfigurationsByChainId).map(({ chainId, nativeCurrency }) => {
276
+ return {
277
+ chainId: chainId,
278
+ nativeCurrency,
279
+ };
280
+ });
281
+ if (__classPrivateFieldGet(this, _TokenRatesController_pollState, "f") === PollState.Active) {
282
+ await this.updateExchangeRates(chainIdAndNativeCurrency);
280
283
  }
281
284
  // Remove state for deleted networks
282
285
  for (const patch of patches) {
@@ -294,16 +297,6 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
294
297
  const tokenAddresses = getTokens(__classPrivateFieldGet(this, _TokenRatesController_allTokens, "f")[chainId]);
295
298
  const detectedTokenAddresses = getTokens(__classPrivateFieldGet(this, _TokenRatesController_allDetectedTokens, "f")[chainId]);
296
299
  return [...new Set([...tokenAddresses, ...detectedTokenAddresses])].sort();
297
- }, _TokenRatesController_getSelectedAccount = function _TokenRatesController_getSelectedAccount() {
298
- const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
299
- return selectedAccount;
300
- }, _TokenRatesController_getChainIdAndTicker = function _TokenRatesController_getChainIdAndTicker() {
301
- const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
302
- const networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
303
- return {
304
- chainId: networkClient.configuration.chainId,
305
- ticker: networkClient.configuration.ticker,
306
- };
307
300
  }, _TokenRatesController_getTokensControllerState = function _TokenRatesController_getTokensControllerState() {
308
301
  const { allTokens, allDetectedTokens } = this.messagingSystem.call('TokensController:getState');
309
302
  return {
@@ -317,15 +310,18 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
317
310
  }, _TokenRatesController_poll =
318
311
  /**
319
312
  * Poll for exchange rate updates.
313
+ *
314
+ * @param chainId - The chain ID.
315
+ * @param nativeCurrency - The native currency.
320
316
  */
321
- async function _TokenRatesController_poll() {
322
- await (0, controller_utils_1.safelyExecute)(() => this.updateExchangeRates());
317
+ async function _TokenRatesController_poll(chainId, nativeCurrency) {
318
+ await (0, controller_utils_1.safelyExecute)(() => this.updateExchangeRates([{ chainId, nativeCurrency }]));
323
319
  // Poll using recursive `setTimeout` instead of `setInterval` so that
324
320
  // requests don't stack if they take longer than the polling interval
325
321
  __classPrivateFieldSet(this, _TokenRatesController_handle, setTimeout(() => {
326
322
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
327
323
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
328
- __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this);
324
+ __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this, chainId, nativeCurrency);
329
325
  }, __classPrivateFieldGet(this, _TokenRatesController_interval, "f")), "f");
330
326
  }, _TokenRatesController_fetchAndMapExchangeRates =
331
327
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TokenRatesController.cjs","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerGetAccountAction,\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n safelyExecute,\n toChecksumHexAddress,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerStateChangeEvent,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { createDeferredPromise, type Hex } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport { reduceInBatchesSerially, TOKEN_PRICES_BATCH_SIZE } from './assetsUtil';\nimport { fetchExchangeRate as fetchNativeCurrencyExchangeRate } from './crypto-compare-service';\nimport type { AbstractTokenPricesService } from './token-prices-service/abstract-token-prices-service';\nimport { getNativeTokenAddress } from './token-prices-service/codefi-v2';\nimport type {\n TokensControllerGetStateAction,\n TokensControllerStateChangeEvent,\n TokensControllerState,\n} from './TokensController';\n\n/**\n * @type Token\n *\n * Token representation\n * @property address - Hex address of the token contract\n * @property decimals - Number of decimals the token uses\n * @property symbol - Symbol of the token\n * @property aggregators - An array containing the token's aggregators\n * @property image - Image of the token, url or bit32 image\n * @property hasBalanceError - 'true' if there is an error while updating the token balance\n * @property isERC721 - 'true' if the token is a ERC721 token\n * @property name - Name of the token\n */\nexport type Token = {\n address: string;\n decimals: number;\n symbol: string;\n aggregators?: string[];\n image?: string;\n hasBalanceError?: boolean;\n isERC721?: boolean;\n name?: string;\n};\n\nconst DEFAULT_INTERVAL = 180000;\n\nexport type ContractExchangeRates = {\n [address: string]: number | undefined;\n};\n\nexport type MarketDataDetails = {\n tokenAddress: `0x${string}`;\n currency: string;\n allTimeHigh: number;\n allTimeLow: number;\n circulatingSupply: number;\n dilutedMarketCap: number;\n high1d: number;\n low1d: number;\n marketCap: number;\n marketCapPercentChange1d: number;\n price: number;\n priceChange1d: number;\n pricePercentChange1d: number;\n pricePercentChange1h: number;\n pricePercentChange1y: number;\n pricePercentChange7d: number;\n pricePercentChange14d: number;\n pricePercentChange30d: number;\n pricePercentChange200d: number;\n totalVolume: number;\n};\n\n/**\n * Represents a mapping of token contract addresses to their market data.\n */\nexport type ContractMarketData = Record<Hex, MarketDataDetails>;\n\nenum PollState {\n Active = 'Active',\n Inactive = 'Inactive',\n}\n\n/**\n * The external actions available to the {@link TokenRatesController}.\n */\nexport type AllowedActions =\n | TokensControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | AccountsControllerGetAccountAction\n | AccountsControllerGetSelectedAccountAction;\n\n/**\n * The external events available to the {@link TokenRatesController}.\n */\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | NetworkControllerStateChangeEvent\n | AccountsControllerSelectedEvmAccountChangeEvent;\n\n/**\n * The name of the {@link TokenRatesController}.\n */\nexport const controllerName = 'TokenRatesController';\n\n/**\n * @type TokenRatesState\n *\n * Token rates controller state\n * @property marketData - Market data for tokens, keyed by chain ID and then token contract address.\n */\nexport type TokenRatesControllerState = {\n marketData: Record<Hex, Record<Hex, MarketDataDetails>>;\n};\n\n/**\n * The action that can be performed to get the state of the {@link TokenRatesController}.\n */\nexport type TokenRatesControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TokenRatesControllerState\n>;\n\n/**\n * The actions that can be performed using the {@link TokenRatesController}.\n */\nexport type TokenRatesControllerActions = TokenRatesControllerGetStateAction;\n\n/**\n * The event that {@link TokenRatesController} can emit.\n */\nexport type TokenRatesControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n TokenRatesControllerState\n>;\n\n/**\n * The events that {@link TokenRatesController} can emit.\n */\nexport type TokenRatesControllerEvents = TokenRatesControllerStateChangeEvent;\n\n/**\n * The messenger of the {@link TokenRatesController} for communication.\n */\nexport type TokenRatesControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n TokenRatesControllerActions | AllowedActions,\n TokenRatesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Uses the CryptoCompare API to fetch the exchange rate between one currency\n * and another, i.e., the multiplier to apply the amount of one currency in\n * order to convert it to another.\n *\n * @param args - The arguments to this function.\n * @param args.from - The currency to convert from.\n * @param args.to - The currency to convert to.\n * @returns The exchange rate between `fromCurrency` to `toCurrency` if one\n * exists, or null if one does not.\n */\nasync function getCurrencyConversionRate({\n from,\n to,\n}: {\n from: string;\n to: string;\n}) {\n const includeUSDRate = false;\n try {\n const result = await fetchNativeCurrencyExchangeRate(\n to,\n from,\n includeUSDRate,\n );\n return result.conversionRate;\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n ) {\n return null;\n }\n throw error;\n }\n}\n\nconst tokenRatesControllerMetadata = {\n marketData: { persist: true, anonymous: false },\n};\n\n/**\n * Get the default {@link TokenRatesController} state.\n *\n * @returns The default {@link TokenRatesController} state.\n */\nexport const getDefaultTokenRatesControllerState =\n (): TokenRatesControllerState => {\n return {\n marketData: {},\n };\n };\n\n/** The input to start polling for the {@link TokenRatesController} */\nexport type TokenRatesPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval for token-to-fiat exchange rates\n * for tokens stored in the TokensController\n */\nexport class TokenRatesController extends StaticIntervalPollingController<TokenRatesPollingInput>()<\n typeof controllerName,\n TokenRatesControllerState,\n TokenRatesControllerMessenger\n> {\n #handle?: ReturnType<typeof setTimeout>;\n\n #pollState = PollState.Inactive;\n\n readonly #tokenPricesService: AbstractTokenPricesService;\n\n #inProcessExchangeRateUpdates: Record<`${Hex}:${string}`, Promise<void>> = {};\n\n #selectedAccountId: string;\n\n #disabled: boolean;\n\n #chainId: Hex;\n\n #ticker: string;\n\n #interval: number;\n\n #allTokens: TokensControllerState['allTokens'];\n\n #allDetectedTokens: TokensControllerState['allDetectedTokens'];\n\n /**\n * Creates a TokenRatesController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The polling interval in ms\n * @param options.disabled - Boolean to track if network requests are blocked\n * @param options.tokenPricesService - An object in charge of retrieving token price\n * @param options.messenger - The messenger instance for communication\n * @param options.state - Initial state to set on this controller\n */\n constructor({\n interval = DEFAULT_INTERVAL,\n disabled = false,\n tokenPricesService,\n messenger,\n state,\n }: {\n interval?: number;\n disabled?: boolean;\n tokenPricesService: AbstractTokenPricesService;\n messenger: TokenRatesControllerMessenger;\n state?: Partial<TokenRatesControllerState>;\n }) {\n super({\n name: controllerName,\n messenger,\n state: { ...getDefaultTokenRatesControllerState(), ...state },\n metadata: tokenRatesControllerMetadata,\n });\n\n this.setIntervalLength(interval);\n this.#tokenPricesService = tokenPricesService;\n this.#disabled = disabled;\n this.#interval = interval;\n\n const { chainId: currentChainId, ticker: currentTicker } =\n this.#getChainIdAndTicker();\n this.#chainId = currentChainId;\n this.#ticker = currentTicker;\n\n this.#selectedAccountId = this.#getSelectedAccount().id;\n\n const { allTokens, allDetectedTokens } = this.#getTokensControllerState();\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n this.#subscribeToTokensStateChange();\n\n this.#subscribeToNetworkStateChange();\n }\n\n #subscribeToTokensStateChange() {\n this.messagingSystem.subscribe(\n 'TokensController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async ({ allTokens, allDetectedTokens }) => {\n if (this.#disabled) {\n return;\n }\n\n const chainIds = [\n ...new Set([\n ...Object.keys(allTokens),\n ...Object.keys(allDetectedTokens),\n ]),\n ] as Hex[];\n\n const chainIdsToUpdate = chainIds.filter(\n (chainId) =>\n !isEqual(this.#allTokens[chainId], allTokens[chainId]) ||\n !isEqual(\n this.#allDetectedTokens[chainId],\n allDetectedTokens[chainId],\n ),\n );\n\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n\n await Promise.allSettled(\n chainIdsToUpdate.map(async (chainId) => {\n const nativeCurrency =\n networkConfigurationsByChainId[chainId as Hex]?.nativeCurrency;\n\n if (nativeCurrency) {\n await this.updateExchangeRatesByChainId({\n chainId: chainId as Hex,\n nativeCurrency,\n });\n }\n }),\n );\n },\n ({ allTokens, allDetectedTokens }) => {\n return { allTokens, allDetectedTokens };\n },\n );\n }\n\n #subscribeToNetworkStateChange() {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async ({ selectedNetworkClientId }, patches) => {\n const {\n configuration: { chainId, ticker },\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n if (this.#chainId !== chainId || this.#ticker !== ticker) {\n this.#chainId = chainId;\n this.#ticker = ticker;\n if (this.#pollState === PollState.Active) {\n await this.updateExchangeRates();\n }\n }\n\n // Remove state for deleted networks\n for (const patch of patches) {\n if (\n patch.op === 'remove' &&\n patch.path[0] === 'networkConfigurationsByChainId'\n ) {\n const removedChainId = patch.path[1] as Hex;\n this.update((state) => {\n delete state.marketData[removedChainId];\n });\n }\n }\n },\n );\n }\n\n /**\n * Get the tokens for the given chain.\n *\n * @param chainId - The chain ID.\n * @returns The list of tokens addresses for the current chain\n */\n #getTokenAddresses(chainId: Hex): Hex[] {\n const getTokens = (allTokens: Record<Hex, { address: string }[]>) =>\n Object.values(allTokens ?? {}).flatMap((tokens) =>\n tokens.map(({ address }) => toChecksumHexAddress(address) as Hex),\n );\n\n const tokenAddresses = getTokens(this.#allTokens[chainId]);\n const detectedTokenAddresses = getTokens(this.#allDetectedTokens[chainId]);\n\n return [...new Set([...tokenAddresses, ...detectedTokenAddresses])].sort();\n }\n\n /**\n * Allows controller to make active and passive polling requests\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Blocks controller from making network calls\n */\n disable(): void {\n this.#disabled = true;\n }\n\n /**\n * Start (or restart) polling.\n */\n async start() {\n this.#stopPoll();\n this.#pollState = PollState.Active;\n await this.#poll();\n }\n\n /**\n * Stop polling.\n */\n stop() {\n this.#stopPoll();\n this.#pollState = PollState.Inactive;\n }\n\n #getSelectedAccount(): InternalAccount {\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n\n return selectedAccount;\n }\n\n #getChainIdAndTicker(): {\n chainId: Hex;\n ticker: string;\n } {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return {\n chainId: networkClient.configuration.chainId,\n ticker: networkClient.configuration.ticker,\n };\n }\n\n #getTokensControllerState(): {\n allTokens: TokensControllerState['allTokens'];\n allDetectedTokens: TokensControllerState['allDetectedTokens'];\n } {\n const { allTokens, allDetectedTokens } = this.messagingSystem.call(\n 'TokensController:getState',\n );\n\n return {\n allTokens,\n allDetectedTokens,\n };\n }\n\n /**\n * Clear the active polling timer, if present.\n */\n #stopPoll() {\n if (this.#handle) {\n clearTimeout(this.#handle);\n }\n }\n\n /**\n * Poll for exchange rate updates.\n */\n async #poll() {\n await safelyExecute(() => this.updateExchangeRates());\n\n // Poll using recursive `setTimeout` instead of `setInterval` so that\n // requests don't stack if they take longer than the polling interval\n this.#handle = setTimeout(() => {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#poll();\n }, this.#interval);\n }\n\n /**\n * Updates exchange rates for all tokens.\n */\n async updateExchangeRates() {\n await this.updateExchangeRatesByChainId({\n chainId: this.#chainId,\n nativeCurrency: this.#ticker,\n });\n }\n\n /**\n * Updates exchange rates for all tokens.\n *\n * @param options - The options to fetch exchange rates.\n * @param options.chainId - The chain ID.\n * @param options.nativeCurrency - The ticker for the chain.\n */\n async updateExchangeRatesByChainId({\n chainId,\n nativeCurrency,\n }: {\n chainId: Hex;\n nativeCurrency: string;\n }) {\n if (this.#disabled) {\n return;\n }\n\n const tokenAddresses = this.#getTokenAddresses(chainId);\n\n // Key dependencies that will trigger a new request instead of aborting:\n // - chainId - different chains require a new request\n // - nativeCurrency - changing native currency requires fetching different rates\n // - tokenAddress length - if we have detected any new tokens, we will need to make a new request for the rates\n const updateKey: `${Hex}:${string}` = `${chainId}:${nativeCurrency}:${tokenAddresses.length}`;\n if (updateKey in this.#inProcessExchangeRateUpdates) {\n // This prevents redundant updates\n // This promise is resolved after the in-progress update has finished,\n // and state has been updated.\n await this.#inProcessExchangeRateUpdates[updateKey];\n return;\n }\n\n const {\n promise: inProgressUpdate,\n resolve: updateSucceeded,\n reject: updateFailed,\n } = createDeferredPromise({ suppressUnhandledRejection: true });\n this.#inProcessExchangeRateUpdates[updateKey] = inProgressUpdate;\n\n try {\n const contractInformations = await this.#fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n\n const marketData = {\n [chainId]: {\n ...(contractInformations ?? {}),\n },\n };\n\n this.update((state) => {\n state.marketData = {\n ...state.marketData,\n ...marketData,\n };\n });\n updateSucceeded();\n } catch (error: unknown) {\n updateFailed(error);\n throw error;\n } finally {\n delete this.#inProcessExchangeRateUpdates[updateKey];\n }\n }\n\n /**\n * Uses the token prices service to retrieve exchange rates for tokens in a\n * particular currency.\n *\n * If the price API does not support the given chain ID, returns an empty\n * object.\n *\n * If the price API does not support the given currency, retrieves exchange\n * rates in a known currency instead, then converts those rates using the\n * exchange rate between the known currency and desired currency.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * exchange rates.\n * @returns A map from token address to its exchange rate in the native\n * currency, or an empty map if no exchange rates can be obtained for the\n * chain ID.\n */\n async #fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n if (!this.#tokenPricesService.validateChainIdSupported(chainId)) {\n return tokenAddresses.reduce((obj, tokenAddress) => {\n obj = {\n ...obj,\n [tokenAddress]: undefined,\n };\n\n return obj;\n }, {});\n }\n\n if (this.#tokenPricesService.validateCurrencySupported(nativeCurrency)) {\n return await this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n }\n\n return await this.#fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n chainId,\n tokenAddresses,\n nativeCurrency,\n });\n }\n\n /**\n * Updates token rates for the given networkClientId\n *\n * @param input - The input for the poll.\n * @param input.chainId - The chain id to poll token rates on.\n */\n async _executePoll({ chainId }: TokenRatesPollingInput): Promise<void> {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n\n const networkConfiguration = networkConfigurationsByChainId[chainId];\n if (!networkConfiguration) {\n console.error(\n `TokenRatesController: No network configuration found for chainId ${chainId}`,\n );\n return;\n }\n\n await this.updateExchangeRatesByChainId({\n chainId,\n nativeCurrency: networkConfiguration.nativeCurrency,\n });\n }\n\n /**\n * Retrieves prices in the given currency for the given tokens on the given\n * chain. Ensures that token addresses are checksum addresses.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n let contractNativeInformations;\n const tokenPricesByTokenAddress = await reduceInBatchesSerially<\n Hex,\n Awaited<ReturnType<AbstractTokenPricesService['fetchTokenPrices']>>\n >({\n values: [...tokenAddresses].sort(),\n batchSize: TOKEN_PRICES_BATCH_SIZE,\n eachBatch: async (allTokenPricesByTokenAddress, batch) => {\n const tokenPricesByTokenAddressForBatch =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: batch,\n chainId,\n currency: nativeCurrency,\n });\n\n return {\n ...allTokenPricesByTokenAddress,\n ...tokenPricesByTokenAddressForBatch,\n };\n },\n initialResult: {},\n });\n contractNativeInformations = tokenPricesByTokenAddress;\n\n // fetch for native token\n if (tokenAddresses.length === 0) {\n const contractNativeInformationsNative =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: [],\n chainId,\n currency: nativeCurrency,\n });\n\n contractNativeInformations = {\n [getNativeTokenAddress(chainId)]: {\n currency: nativeCurrency,\n ...contractNativeInformationsNative[getNativeTokenAddress(chainId)],\n },\n };\n }\n return Object.entries(contractNativeInformations).reduce(\n (obj, [tokenAddress, token]) => {\n obj = {\n ...obj,\n [tokenAddress]: { ...token },\n };\n\n return obj;\n },\n {},\n );\n }\n\n /**\n * If the price API does not support a given native currency, then we need to\n * convert it to a fallback currency and feed that currency into the price\n * API, then convert the prices to our desired native currency.\n *\n * @param args - The arguments to this function.\n * @param args.chainId - The chain id to fetch prices for.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n chainId,\n tokenAddresses,\n nativeCurrency,\n }: {\n chainId: Hex;\n tokenAddresses: Hex[];\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n const [\n contractExchangeInformations,\n fallbackCurrencyToNativeCurrencyConversionRate,\n ] = await Promise.all([\n this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency: FALL_BACK_VS_CURRENCY,\n }),\n getCurrencyConversionRate({\n from: FALL_BACK_VS_CURRENCY,\n to: nativeCurrency,\n }),\n ]);\n\n if (fallbackCurrencyToNativeCurrencyConversionRate === null) {\n return {};\n }\n\n // Converts the price in the fallback currency to the native currency\n const convertFallbackToNative = (value: number | undefined) =>\n value !== undefined && value !== null\n ? value * fallbackCurrencyToNativeCurrencyConversionRate\n : undefined;\n\n const updatedContractExchangeRates = Object.entries(\n contractExchangeInformations,\n ).reduce((acc, [tokenAddress, token]) => {\n acc = {\n ...acc,\n [tokenAddress]: {\n ...token,\n currency: nativeCurrency,\n price: convertFallbackToNative(token.price),\n marketCap: convertFallbackToNative(token.marketCap),\n allTimeHigh: convertFallbackToNative(token.allTimeHigh),\n allTimeLow: convertFallbackToNative(token.allTimeLow),\n totalVolume: convertFallbackToNative(token.totalVolume),\n high1d: convertFallbackToNative(token.high1d),\n low1d: convertFallbackToNative(token.low1d),\n dilutedMarketCap: convertFallbackToNative(token.dilutedMarketCap),\n },\n };\n return acc;\n }, {});\n\n return updatedContractExchangeRates;\n }\n\n /**\n * Reset the controller state to the default state.\n */\n resetState() {\n this.update(() => {\n return getDefaultTokenRatesControllerState();\n });\n }\n}\n\nexport default TokenRatesController;\n"]}
1
+ {"version":3,"file":"TokenRatesController.cjs","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAUA,iEAIoC;AAMpC,qEAA+E;AAC/E,2CAAkE;AAClE,mCAAiC;AAEjC,iDAAgF;AAChF,+EAAgG;AAEhG,oEAAyE;AA+BzE,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAkChC,IAAK,SAGJ;AAHD,WAAK,SAAS;IACZ,8BAAiB,CAAA;IACjB,kCAAqB,CAAA;AACvB,CAAC,EAHI,SAAS,KAAT,SAAS,QAGb;AAoBD;;GAEG;AACU,QAAA,cAAc,GAAG,sBAAsB,CAAC;AAiDrD;;;;;;;;;;GAUG;AACH,KAAK,UAAU,yBAAyB,CAAC,EACvC,IAAI,EACJ,EAAE,GAIH;IACC,MAAM,cAAc,GAAG,KAAK,CAAC;IAC7B,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,IAAA,0CAA+B,EAClD,EAAE,EACF,IAAI,EACJ,cAAc,CACf,CAAC;QACF,OAAO,MAAM,CAAC,cAAc,CAAC;KAC9B;IAAC,OAAO,KAAK,EAAE;QACd,IACE,KAAK,YAAY,KAAK;YACtB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,0CAA0C,CAAC,EAClE;YACA,OAAO,IAAI,CAAC;SACb;QACD,MAAM,KAAK,CAAC;KACb;AACH,CAAC;AAED,MAAM,4BAA4B,GAAG;IACnC,UAAU,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE;CAChD,CAAC;AAEF;;;;GAIG;AACI,MAAM,mCAAmC,GAC9C,GAA8B,EAAE;IAC9B,OAAO;QACL,UAAU,EAAE,EAAE;KACf,CAAC;AACJ,CAAC,CAAC;AALS,QAAA,mCAAmC,uCAK5C;AAUJ;;;GAGG;AACH,MAAa,oBAAqB,SAAQ,IAAA,oDAA+B,GAIxE;IAiBC;;;;;;;;;OASG;IACH,YAAY,EACV,QAAQ,GAAG,gBAAgB,EAC3B,QAAQ,GAAG,KAAK,EAChB,kBAAkB,EAClB,SAAS,EACT,KAAK,GAON;QACC,KAAK,CAAC;YACJ,IAAI,EAAE,sBAAc;YACpB,SAAS;YACT,KAAK,EAAE,EAAE,GAAG,IAAA,2CAAmC,GAAE,EAAE,GAAG,KAAK,EAAE;YAC7D,QAAQ,EAAE,4BAA4B;SACvC,CAAC,CAAC;;QA5CL,+CAAwC;QAExC,0CAAa,SAAS,CAAC,QAAQ,EAAC;QAEvB,2DAAgD;QAEzD,6DAA2E,EAAE,EAAC;QAE9E,iDAAmB;QAEnB,iDAAkB;QAElB,kDAA+C;QAE/C,0DAA+D;QAgC7D,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjC,uBAAA,IAAI,4CAAuB,kBAAkB,MAAA,CAAC;QAC9C,uBAAA,IAAI,kCAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,kCAAa,QAAQ,MAAA,CAAC;QAE1B,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,uBAAA,IAAI,uFAA0B,MAA9B,IAAI,CAA4B,CAAC;QAC1E,uBAAA,IAAI,mCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,2CAAsB,iBAAiB,MAAA,CAAC;QAE5C,uBAAA,IAAI,2FAA8B,MAAlC,IAAI,CAAgC,CAAC;QAErC,uBAAA,IAAI,4FAA+B,MAAnC,IAAI,CAAiC,CAAC;IACxC,CAAC;IA2GD;;OAEG;IACH,MAAM;QACJ,uBAAA,IAAI,kCAAa,KAAK,MAAA,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,uBAAA,IAAI,kCAAa,IAAI,MAAA,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK,CAAC,OAAY,EAAE,cAAsB;QAC9C,uBAAA,IAAI,uEAAU,MAAd,IAAI,CAAY,CAAC;QACjB,uBAAA,IAAI,mCAAc,SAAS,CAAC,MAAM,MAAA,CAAC;QACnC,MAAM,uBAAA,IAAI,mEAAM,MAAV,IAAI,EAAO,OAAO,EAAE,cAAc,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,IAAI;QACF,uBAAA,IAAI,uEAAU,MAAd,IAAI,CAAY,CAAC;QACjB,uBAAA,IAAI,mCAAc,SAAS,CAAC,QAAQ,MAAA,CAAC;IACvC,CAAC;IA6CD;;;;OAIG;IACH,KAAK,CAAC,mBAAmB,CACvB,wBAGG;QAEH,MAAM,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,CAAC,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACH;;;;OAIG;IACH,KAAK,CAAC,4BAA4B,CAChC,wBAGG;QAEH,IAAI,uBAAA,IAAI,sCAAU,EAAE;YAClB,OAAO;SACR;QAED,6DAA6D;QAC7D,MAAM,cAAc,GAAG,wBAAwB,CAAC,GAAG,CACjD,KAAK,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;YACpC,MAAM,cAAc,GAAG,uBAAA,IAAI,gFAAmB,MAAvB,IAAI,EAAoB,OAAO,CAAC,CAAC;YACxD,0FAA0F;YAC1F,MAAM,SAAS,GAAuB,GAAG,OAAO,IAAI,cAAc,IAAI,cAAc,CAAC,MAAM,EAAE,CAAC;YAE9F,IAAI,SAAS,IAAI,uBAAA,IAAI,0DAA8B,EAAE;gBACnD,oDAAoD;gBACpD,MAAM,uBAAA,IAAI,0DAA8B,CAAC,SAAS,CAAC,CAAC;gBACpD,OAAO,IAAI,CAAC;aACb;YAED,kDAAkD;YAClD,MAAM,EACJ,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,YAAY,GACrB,GAAG,IAAA,6BAAqB,EAAC,EAAE,0BAA0B,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,uBAAA,IAAI,0DAA8B,CAAC,SAAS,CAAC,GAAG,gBAAgB,CAAC;YAEjE,IAAI;gBACF,MAAM,oBAAoB,GAAG,MAAM,uBAAA,IAAI,uFAA0B,MAA9B,IAAI,EAA2B;oBAChE,cAAc;oBACd,OAAO;oBACP,cAAc;iBACf,CAAC,CAAC;gBAEH,qEAAqE;gBACrE,MAAM,UAAU,GAAG;oBACjB,CAAC,OAAO,CAAC,EAAE;wBACT,GAAG,CAAC,oBAAoB,IAAI,EAAE,CAAC;qBAChC;iBACF,CAAC;gBAEF,eAAe,EAAE,CAAC;gBAClB,OAAO,UAAU,CAAC;aACnB;YAAC,OAAO,KAAc,EAAE;gBACvB,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,MAAM,KAAK,CAAC;aACb;oBAAS;gBACR,wCAAwC;gBACxC,OAAO,uBAAA,IAAI,0DAA8B,CAAC,SAAS,CAAC,CAAC;aACtD;QACH,CAAC,CACF,CAAC;QAEF,0CAA0C;QAC1C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAEzD,4DAA4D;QAC5D,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACxD,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,KAAK,EAAE;gBACjD,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;aACnC;YACD,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,gHAAgH;QAChH,IAAI,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC9C,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,UAAU,GAAG;oBACjB,GAAG,KAAK,CAAC,UAAU;oBACnB,GAAG,kBAAkB;iBACtB,CAAC;YACJ,CAAC,CAAC,CAAC;SACJ;IACH,CAAC;IAyDD;;;;;OAKG;IACH,KAAK,CAAC,YAAY,CAAC,EACjB,wBAAwB,GACD;QACvB,MAAM,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,CAAC,CAAC;IACpE,CAAC;IAmJD;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;YACf,OAAO,IAAA,2CAAmC,GAAE,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AA3jBD,oDA2jBC;;IAzfG,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,8BAA8B;IAC9B,gFAAgF;IAChF,kEAAkE;IAClE,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,EAAE;QACzC,IAAI,uBAAA,IAAI,sCAAU,EAAE;YAClB,OAAO;SACR;QAED,MAAM,EAAE,8BAA8B,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAClE,4BAA4B,CAC7B,CAAC;QAEF,MAAM,QAAQ,GAAG;YACf,GAAG,IAAI,GAAG,CAAC;gBACT,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;gBACzB,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC;aAClC,CAAC;SACM,CAAC;QAEX,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CACtC,CAAC,OAAO,EAAE,EAAE,CACV,CAAC,IAAA,gBAAO,EAAC,uBAAA,IAAI,uCAAW,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;YACtD,CAAC,IAAA,gBAAO,EACN,uBAAA,IAAI,+CAAmB,CAAC,OAAO,CAAC,EAChC,iBAAiB,CAAC,OAAO,CAAC,CAC3B,CACJ,CAAC;QAEF,uBAAA,IAAI,mCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,2CAAsB,iBAAiB,MAAA,CAAC;QAE5C,MAAM,wBAAwB,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YAChE,OAAO;gBACL,OAAO,EAAE,OAAc;gBACvB,cAAc,EACZ,8BAA8B,CAAC,OAAO,CAAC,EAAE,cAAc;aAC1D,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,4BAA4B,CAAC,wBAAwB,CAAC,CAAC;IACpE,CAAC,EACD,CAAC,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,EAAE;QACnC,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC1C,CAAC,CACF,CAAC;AACJ,CAAC;IAGC,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,+BAA+B;IAC/B,gFAAgF;IAChF,kEAAkE;IAClE,KAAK,EAAE,EAAE,8BAA8B,EAAE,EAAE,OAAO,EAAE,EAAE;QACpD,MAAM,wBAAwB,GAGxB,MAAM,CAAC,MAAM,CAAC,8BAA8B,CAAC,CAAC,GAAG,CACrD,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;YAC9B,OAAO;gBACL,OAAO,EAAE,OAAc;gBACvB,cAAc;aACf,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,IAAI,uBAAA,IAAI,uCAAW,KAAK,SAAS,CAAC,MAAM,EAAE;YACxC,MAAM,IAAI,CAAC,mBAAmB,CAAC,wBAAwB,CAAC,CAAC;SAC1D;QAED,oCAAoC;QACpC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;YAC3B,IACE,KAAK,CAAC,EAAE,KAAK,QAAQ;gBACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,gCAAgC,EAClD;gBACA,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAQ,CAAC;gBAC5C,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,OAAO,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;gBAC1C,CAAC,CAAC,CAAC;aACJ;SACF;IACH,CAAC,CACF,CAAC;AACJ,CAAC,6FAQkB,OAAY;IAC7B,MAAM,SAAS,GAAG,CAAC,SAA6C,EAAE,EAAE,CAClE,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAChD,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,IAAA,uCAAoB,EAAC,OAAO,CAAQ,CAAC,CAClE,CAAC;IAEJ,MAAM,cAAc,GAAG,SAAS,CAAC,uBAAA,IAAI,uCAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3D,MAAM,sBAAsB,GAAG,SAAS,CAAC,uBAAA,IAAI,+CAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;IAE3E,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,cAAc,EAAE,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7E,CAAC;IAwCC,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAChE,2BAA2B,CAC5B,CAAC;IAEF,OAAO;QACL,SAAS;QACT,iBAAiB;KAClB,CAAC;AACJ,CAAC;IAMC,IAAI,uBAAA,IAAI,oCAAQ,EAAE;QAChB,YAAY,CAAC,uBAAA,IAAI,oCAAQ,CAAC,CAAC;KAC5B;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,qCAAO,OAAY,EAAE,cAAsB;IAC9C,MAAM,IAAA,gCAAa,EAAC,GAAG,EAAE,CACvB,IAAI,CAAC,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CACxD,CAAC;IAEF,qEAAqE;IACrE,qEAAqE;IACrE,uBAAA,IAAI,gCAAW,UAAU,CAAC,GAAG,EAAE;QAC7B,gFAAgF;QAChF,mEAAmE;QACnE,uBAAA,IAAI,mEAAM,MAAV,IAAI,EAAO,OAAO,EAAE,cAAc,CAAC,CAAC;IACtC,CAAC,EAAE,uBAAA,IAAI,sCAAU,CAAC,MAAA,CAAC;AACrB,CAAC;AA0GD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,KAAK,yDAA2B,EAC9B,cAAc,EACd,OAAO,EACP,cAAc,GAKf;IACC,IAAI,CAAC,uBAAA,IAAI,gDAAoB,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE;QAC/D,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,YAAY,EAAE,EAAE;YACjD,GAAG,GAAG;gBACJ,GAAG,GAAG;gBACN,CAAC,YAAY,CAAC,EAAE,SAAS;aAC1B,CAAC;YAEF,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAAE,CAAC,CAAC;KACR;IAED,IAAI,uBAAA,IAAI,gDAAoB,CAAC,yBAAyB,CAAC,cAAc,CAAC,EAAE;QACtE,OAAO,MAAM,uBAAA,IAAI,iHAAoD,MAAxD,IAAI,EAAqD;YACpE,cAAc;YACd,OAAO;YACP,cAAc;SACf,CAAC,CAAC;KACJ;IAED,OAAO,MAAM,uBAAA,IAAI,mHAAsD,MAA1D,IAAI,EAAuD;QACtE,OAAO;QACP,cAAc;QACd,cAAc;KACf,CAAC,CAAC;AACL,CAAC;AAcD;;;;;;;;;;;GAWG;AACH,KAAK,mFAAqD,EACxD,cAAc,EACd,OAAO,EACP,cAAc,GAKf;IACC,IAAI,0BAA0B,CAAC;IAC/B,MAAM,yBAAyB,GAAG,MAAM,IAAA,oCAAuB,EAG7D;QACA,MAAM,EAAE,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,EAAE;QAClC,SAAS,EAAE,oCAAuB;QAClC,SAAS,EAAE,KAAK,EAAE,4BAA4B,EAAE,KAAK,EAAE,EAAE;YACvD,MAAM,iCAAiC,GACrC,MAAM,uBAAA,IAAI,gDAAoB,CAAC,gBAAgB,CAAC;gBAC9C,cAAc,EAAE,KAAK;gBACrB,OAAO;gBACP,QAAQ,EAAE,cAAc;aACzB,CAAC,CAAC;YAEL,OAAO;gBACL,GAAG,4BAA4B;gBAC/B,GAAG,iCAAiC;aACrC,CAAC;QACJ,CAAC;QACD,aAAa,EAAE,EAAE;KAClB,CAAC,CAAC;IACH,0BAA0B,GAAG,yBAAyB,CAAC;IAEvD,yBAAyB;IACzB,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE;QAC/B,MAAM,gCAAgC,GACpC,MAAM,uBAAA,IAAI,gDAAoB,CAAC,gBAAgB,CAAC;YAC9C,cAAc,EAAE,EAAE;YAClB,OAAO;YACP,QAAQ,EAAE,cAAc;SACzB,CAAC,CAAC;QAEL,0BAA0B,GAAG;YAC3B,CAAC,IAAA,iCAAqB,EAAC,OAAO,CAAC,CAAC,EAAE;gBAChC,QAAQ,EAAE,cAAc;gBACxB,GAAG,gCAAgC,CAAC,IAAA,iCAAqB,EAAC,OAAO,CAAC,CAAC;aACpE;SACF,CAAC;KACH;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,MAAM,CACtD,CAAC,GAAG,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,EAAE;QAC7B,GAAG,GAAG;YACJ,GAAG,GAAG;YACN,CAAC,YAAY,CAAC,EAAE,EAAE,GAAG,KAAK,EAAE;SAC7B,CAAC;QAEF,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAE,CACH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,qFAAuD,EAC1D,OAAO,EACP,cAAc,EACd,cAAc,GAKf;IACC,MAAM,CACJ,4BAA4B,EAC5B,8CAA8C,EAC/C,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACpB,uBAAA,IAAI,iHAAoD,MAAxD,IAAI,EAAqD;YACvD,cAAc;YACd,OAAO;YACP,cAAc,EAAE,wCAAqB;SACtC,CAAC;QACF,yBAAyB,CAAC;YACxB,IAAI,EAAE,wCAAqB;YAC3B,EAAE,EAAE,cAAc;SACnB,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,8CAA8C,KAAK,IAAI,EAAE;QAC3D,OAAO,EAAE,CAAC;KACX;IAED,qEAAqE;IACrE,MAAM,uBAAuB,GAAG,CAAC,KAAyB,EAAE,EAAE,CAC5D,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QACnC,CAAC,CAAC,KAAK,GAAG,8CAA8C;QACxD,CAAC,CAAC,SAAS,CAAC;IAEhB,MAAM,4BAA4B,GAAG,MAAM,CAAC,OAAO,CACjD,4BAA4B,CAC7B,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,EAAE;QACtC,GAAG,GAAG;YACJ,GAAG,GAAG;YACN,CAAC,YAAY,CAAC,EAAE;gBACd,GAAG,KAAK;gBACR,QAAQ,EAAE,cAAc;gBACxB,KAAK,EAAE,uBAAuB,CAAC,KAAK,CAAC,KAAK,CAAC;gBAC3C,SAAS,EAAE,uBAAuB,CAAC,KAAK,CAAC,SAAS,CAAC;gBACnD,WAAW,EAAE,uBAAuB,CAAC,KAAK,CAAC,WAAW,CAAC;gBACvD,UAAU,EAAE,uBAAuB,CAAC,KAAK,CAAC,UAAU,CAAC;gBACrD,WAAW,EAAE,uBAAuB,CAAC,KAAK,CAAC,WAAW,CAAC;gBACvD,MAAM,EAAE,uBAAuB,CAAC,KAAK,CAAC,MAAM,CAAC;gBAC7C,KAAK,EAAE,uBAAuB,CAAC,KAAK,CAAC,KAAK,CAAC;gBAC3C,gBAAgB,EAAE,uBAAuB,CAAC,KAAK,CAAC,gBAAgB,CAAC;aAClE;SACF,CAAC;QACF,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,4BAA4B,CAAC;AACtC,CAAC;AAYH,kBAAe,oBAAoB,CAAC","sourcesContent":["import type {\n AccountsControllerGetAccountAction,\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n safelyExecute,\n toChecksumHexAddress,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerStateChangeEvent,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { createDeferredPromise, type Hex } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport { reduceInBatchesSerially, TOKEN_PRICES_BATCH_SIZE } from './assetsUtil';\nimport { fetchExchangeRate as fetchNativeCurrencyExchangeRate } from './crypto-compare-service';\nimport type { AbstractTokenPricesService } from './token-prices-service/abstract-token-prices-service';\nimport { getNativeTokenAddress } from './token-prices-service/codefi-v2';\nimport type {\n TokensControllerGetStateAction,\n TokensControllerStateChangeEvent,\n TokensControllerState,\n} from './TokensController';\n\n/**\n * @type Token\n *\n * Token representation\n * @property address - Hex address of the token contract\n * @property decimals - Number of decimals the token uses\n * @property symbol - Symbol of the token\n * @property aggregators - An array containing the token's aggregators\n * @property image - Image of the token, url or bit32 image\n * @property hasBalanceError - 'true' if there is an error while updating the token balance\n * @property isERC721 - 'true' if the token is a ERC721 token\n * @property name - Name of the token\n */\nexport type Token = {\n address: string;\n decimals: number;\n symbol: string;\n aggregators?: string[];\n image?: string;\n hasBalanceError?: boolean;\n isERC721?: boolean;\n name?: string;\n};\n\nconst DEFAULT_INTERVAL = 180000;\n\nexport type ContractExchangeRates = {\n [address: string]: number | undefined;\n};\n\nexport type MarketDataDetails = {\n tokenAddress: `0x${string}`;\n currency: string;\n allTimeHigh: number;\n allTimeLow: number;\n circulatingSupply: number;\n dilutedMarketCap: number;\n high1d: number;\n low1d: number;\n marketCap: number;\n marketCapPercentChange1d: number;\n price: number;\n priceChange1d: number;\n pricePercentChange1d: number;\n pricePercentChange1h: number;\n pricePercentChange1y: number;\n pricePercentChange7d: number;\n pricePercentChange14d: number;\n pricePercentChange30d: number;\n pricePercentChange200d: number;\n totalVolume: number;\n};\n\n/**\n * Represents a mapping of token contract addresses to their market data.\n */\nexport type ContractMarketData = Record<Hex, MarketDataDetails>;\n\nenum PollState {\n Active = 'Active',\n Inactive = 'Inactive',\n}\n\n/**\n * The external actions available to the {@link TokenRatesController}.\n */\nexport type AllowedActions =\n | TokensControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | AccountsControllerGetAccountAction\n | AccountsControllerGetSelectedAccountAction;\n\n/**\n * The external events available to the {@link TokenRatesController}.\n */\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | NetworkControllerStateChangeEvent\n | AccountsControllerSelectedEvmAccountChangeEvent;\n\n/**\n * The name of the {@link TokenRatesController}.\n */\nexport const controllerName = 'TokenRatesController';\n\n/**\n * @type TokenRatesState\n *\n * Token rates controller state\n * @property marketData - Market data for tokens, keyed by chain ID and then token contract address.\n */\nexport type TokenRatesControllerState = {\n marketData: Record<Hex, Record<Hex, MarketDataDetails>>;\n};\n\n/**\n * The action that can be performed to get the state of the {@link TokenRatesController}.\n */\nexport type TokenRatesControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TokenRatesControllerState\n>;\n\n/**\n * The actions that can be performed using the {@link TokenRatesController}.\n */\nexport type TokenRatesControllerActions = TokenRatesControllerGetStateAction;\n\n/**\n * The event that {@link TokenRatesController} can emit.\n */\nexport type TokenRatesControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n TokenRatesControllerState\n>;\n\n/**\n * The events that {@link TokenRatesController} can emit.\n */\nexport type TokenRatesControllerEvents = TokenRatesControllerStateChangeEvent;\n\n/**\n * The messenger of the {@link TokenRatesController} for communication.\n */\nexport type TokenRatesControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n TokenRatesControllerActions | AllowedActions,\n TokenRatesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Uses the CryptoCompare API to fetch the exchange rate between one currency\n * and another, i.e., the multiplier to apply the amount of one currency in\n * order to convert it to another.\n *\n * @param args - The arguments to this function.\n * @param args.from - The currency to convert from.\n * @param args.to - The currency to convert to.\n * @returns The exchange rate between `fromCurrency` to `toCurrency` if one\n * exists, or null if one does not.\n */\nasync function getCurrencyConversionRate({\n from,\n to,\n}: {\n from: string;\n to: string;\n}) {\n const includeUSDRate = false;\n try {\n const result = await fetchNativeCurrencyExchangeRate(\n to,\n from,\n includeUSDRate,\n );\n return result.conversionRate;\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n ) {\n return null;\n }\n throw error;\n }\n}\n\nconst tokenRatesControllerMetadata = {\n marketData: { persist: true, anonymous: false },\n};\n\n/**\n * Get the default {@link TokenRatesController} state.\n *\n * @returns The default {@link TokenRatesController} state.\n */\nexport const getDefaultTokenRatesControllerState =\n (): TokenRatesControllerState => {\n return {\n marketData: {},\n };\n };\n\n/** The input to start polling for the {@link TokenRatesController} */\nexport type TokenRatesPollingInput = {\n chainIdAndNativeCurrency: {\n chainId: Hex;\n nativeCurrency: string;\n }[];\n};\n\n/**\n * Controller that passively polls on a set interval for token-to-fiat exchange rates\n * for tokens stored in the TokensController\n */\nexport class TokenRatesController extends StaticIntervalPollingController<TokenRatesPollingInput>()<\n typeof controllerName,\n TokenRatesControllerState,\n TokenRatesControllerMessenger\n> {\n #handle?: ReturnType<typeof setTimeout>;\n\n #pollState = PollState.Inactive;\n\n readonly #tokenPricesService: AbstractTokenPricesService;\n\n #inProcessExchangeRateUpdates: Record<`${Hex}:${string}`, Promise<void>> = {};\n\n #disabled: boolean;\n\n #interval: number;\n\n #allTokens: TokensControllerState['allTokens'];\n\n #allDetectedTokens: TokensControllerState['allDetectedTokens'];\n\n /**\n * Creates a TokenRatesController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The polling interval in ms\n * @param options.disabled - Boolean to track if network requests are blocked\n * @param options.tokenPricesService - An object in charge of retrieving token price\n * @param options.messenger - The messenger instance for communication\n * @param options.state - Initial state to set on this controller\n */\n constructor({\n interval = DEFAULT_INTERVAL,\n disabled = false,\n tokenPricesService,\n messenger,\n state,\n }: {\n interval?: number;\n disabled?: boolean;\n tokenPricesService: AbstractTokenPricesService;\n messenger: TokenRatesControllerMessenger;\n state?: Partial<TokenRatesControllerState>;\n }) {\n super({\n name: controllerName,\n messenger,\n state: { ...getDefaultTokenRatesControllerState(), ...state },\n metadata: tokenRatesControllerMetadata,\n });\n\n this.setIntervalLength(interval);\n this.#tokenPricesService = tokenPricesService;\n this.#disabled = disabled;\n this.#interval = interval;\n\n const { allTokens, allDetectedTokens } = this.#getTokensControllerState();\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n this.#subscribeToTokensStateChange();\n\n this.#subscribeToNetworkStateChange();\n }\n\n #subscribeToTokensStateChange() {\n this.messagingSystem.subscribe(\n 'TokensController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async ({ allTokens, allDetectedTokens }) => {\n if (this.#disabled) {\n return;\n }\n\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n\n const chainIds = [\n ...new Set([\n ...Object.keys(allTokens),\n ...Object.keys(allDetectedTokens),\n ]),\n ] as Hex[];\n\n const chainIdsToUpdate = chainIds.filter(\n (chainId) =>\n !isEqual(this.#allTokens[chainId], allTokens[chainId]) ||\n !isEqual(\n this.#allDetectedTokens[chainId],\n allDetectedTokens[chainId],\n ),\n );\n\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n const chainIdAndNativeCurrency = chainIdsToUpdate.map((chainId) => {\n return {\n chainId: chainId as Hex,\n nativeCurrency:\n networkConfigurationsByChainId[chainId]?.nativeCurrency,\n };\n });\n\n await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);\n },\n ({ allTokens, allDetectedTokens }) => {\n return { allTokens, allDetectedTokens };\n },\n );\n }\n\n #subscribeToNetworkStateChange() {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async ({ networkConfigurationsByChainId }, patches) => {\n const chainIdAndNativeCurrency: {\n chainId: Hex;\n nativeCurrency: string;\n }[] = Object.values(networkConfigurationsByChainId).map(\n ({ chainId, nativeCurrency }) => {\n return {\n chainId: chainId as Hex,\n nativeCurrency,\n };\n },\n );\n\n if (this.#pollState === PollState.Active) {\n await this.updateExchangeRates(chainIdAndNativeCurrency);\n }\n\n // Remove state for deleted networks\n for (const patch of patches) {\n if (\n patch.op === 'remove' &&\n patch.path[0] === 'networkConfigurationsByChainId'\n ) {\n const removedChainId = patch.path[1] as Hex;\n this.update((state) => {\n delete state.marketData[removedChainId];\n });\n }\n }\n },\n );\n }\n\n /**\n * Get the tokens for the given chain.\n *\n * @param chainId - The chain ID.\n * @returns The list of tokens addresses for the current chain\n */\n #getTokenAddresses(chainId: Hex): Hex[] {\n const getTokens = (allTokens: Record<Hex, { address: string }[]>) =>\n Object.values(allTokens ?? {}).flatMap((tokens) =>\n tokens.map(({ address }) => toChecksumHexAddress(address) as Hex),\n );\n\n const tokenAddresses = getTokens(this.#allTokens[chainId]);\n const detectedTokenAddresses = getTokens(this.#allDetectedTokens[chainId]);\n\n return [...new Set([...tokenAddresses, ...detectedTokenAddresses])].sort();\n }\n\n /**\n * Allows controller to make active and passive polling requests\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Blocks controller from making network calls\n */\n disable(): void {\n this.#disabled = true;\n }\n\n /**\n * Start (or restart) polling.\n *\n * @param chainId - The chain ID.\n * @param nativeCurrency - The native currency.\n */\n async start(chainId: Hex, nativeCurrency: string) {\n this.#stopPoll();\n this.#pollState = PollState.Active;\n await this.#poll(chainId, nativeCurrency);\n }\n\n /**\n * Stop polling.\n */\n stop() {\n this.#stopPoll();\n this.#pollState = PollState.Inactive;\n }\n\n #getTokensControllerState(): {\n allTokens: TokensControllerState['allTokens'];\n allDetectedTokens: TokensControllerState['allDetectedTokens'];\n } {\n const { allTokens, allDetectedTokens } = this.messagingSystem.call(\n 'TokensController:getState',\n );\n\n return {\n allTokens,\n allDetectedTokens,\n };\n }\n\n /**\n * Clear the active polling timer, if present.\n */\n #stopPoll() {\n if (this.#handle) {\n clearTimeout(this.#handle);\n }\n }\n\n /**\n * Poll for exchange rate updates.\n *\n * @param chainId - The chain ID.\n * @param nativeCurrency - The native currency.\n */\n async #poll(chainId: Hex, nativeCurrency: string) {\n await safelyExecute(() =>\n this.updateExchangeRates([{ chainId, nativeCurrency }]),\n );\n\n // Poll using recursive `setTimeout` instead of `setInterval` so that\n // requests don't stack if they take longer than the polling interval\n this.#handle = setTimeout(() => {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#poll(chainId, nativeCurrency);\n }, this.#interval);\n }\n\n /**\n * Updates exchange rates for all tokens.\n *\n * @param chainIdAndNativeCurrency - The chain ID and native currency.\n */\n async updateExchangeRates(\n chainIdAndNativeCurrency: {\n chainId: Hex;\n nativeCurrency: string;\n }[],\n ) {\n await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);\n }\n\n /**\n * Updates exchange rates for all tokens.\n *\n * @param chainIds - The chain IDs.\n * @returns A promise that resolves when all chain updates complete.\n */\n /**\n * Updates exchange rates for all tokens.\n *\n * @param chainIdAndNativeCurrency - The chain ID and native currency.\n */\n async updateExchangeRatesByChainId(\n chainIdAndNativeCurrency: {\n chainId: Hex;\n nativeCurrency: string;\n }[],\n ): Promise<void> {\n if (this.#disabled) {\n return;\n }\n\n // Create a promise for each chainId to fetch exchange rates.\n const updatePromises = chainIdAndNativeCurrency.map(\n async ({ chainId, nativeCurrency }) => {\n const tokenAddresses = this.#getTokenAddresses(chainId);\n // Build a unique key based on chainId, nativeCurrency, and the number of token addresses.\n const updateKey: `${Hex}:${string}` = `${chainId}:${nativeCurrency}:${tokenAddresses.length}`;\n\n if (updateKey in this.#inProcessExchangeRateUpdates) {\n // Await any ongoing update to avoid redundant work.\n await this.#inProcessExchangeRateUpdates[updateKey];\n return null;\n }\n\n // Create a deferred promise to track this update.\n const {\n promise: inProgressUpdate,\n resolve: updateSucceeded,\n reject: updateFailed,\n } = createDeferredPromise({ suppressUnhandledRejection: true });\n this.#inProcessExchangeRateUpdates[updateKey] = inProgressUpdate;\n\n try {\n const contractInformations = await this.#fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n\n // Each promise returns an object with the market data for the chain.\n const marketData = {\n [chainId]: {\n ...(contractInformations ?? {}),\n },\n };\n\n updateSucceeded();\n return marketData;\n } catch (error: unknown) {\n updateFailed(error);\n throw error;\n } finally {\n // Cleanup the tracking for this update.\n delete this.#inProcessExchangeRateUpdates[updateKey];\n }\n },\n );\n\n // Wait for all update promises to settle.\n const results = await Promise.allSettled(updatePromises);\n\n // Merge all successful market data updates into one object.\n const combinedMarketData = results.reduce((acc, result) => {\n if (result.status === 'fulfilled' && result.value) {\n acc = { ...acc, ...result.value };\n }\n return acc;\n }, {});\n\n // Call this.update only once with the combined market data to reduce the number of state changes and re-renders\n if (Object.keys(combinedMarketData).length > 0) {\n this.update((state) => {\n state.marketData = {\n ...state.marketData,\n ...combinedMarketData,\n };\n });\n }\n }\n\n /**\n * Uses the token prices service to retrieve exchange rates for tokens in a\n * particular currency.\n *\n * If the price API does not support the given chain ID, returns an empty\n * object.\n *\n * If the price API does not support the given currency, retrieves exchange\n * rates in a known currency instead, then converts those rates using the\n * exchange rate between the known currency and desired currency.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * exchange rates.\n * @returns A map from token address to its exchange rate in the native\n * currency, or an empty map if no exchange rates can be obtained for the\n * chain ID.\n */\n async #fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n if (!this.#tokenPricesService.validateChainIdSupported(chainId)) {\n return tokenAddresses.reduce((obj, tokenAddress) => {\n obj = {\n ...obj,\n [tokenAddress]: undefined,\n };\n\n return obj;\n }, {});\n }\n\n if (this.#tokenPricesService.validateCurrencySupported(nativeCurrency)) {\n return await this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n }\n\n return await this.#fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n chainId,\n tokenAddresses,\n nativeCurrency,\n });\n }\n\n /**\n * Updates token rates for the given networkClientId\n *\n * @param input - The input for the poll.\n * @param input.chainIdAndNativeCurrency - The chain ids and native currencies to poll token rates on.\n */\n async _executePoll({\n chainIdAndNativeCurrency,\n }: TokenRatesPollingInput): Promise<void> {\n await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);\n }\n\n /**\n * Retrieves prices in the given currency for the given tokens on the given\n * chain. Ensures that token addresses are checksum addresses.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n let contractNativeInformations;\n const tokenPricesByTokenAddress = await reduceInBatchesSerially<\n Hex,\n Awaited<ReturnType<AbstractTokenPricesService['fetchTokenPrices']>>\n >({\n values: [...tokenAddresses].sort(),\n batchSize: TOKEN_PRICES_BATCH_SIZE,\n eachBatch: async (allTokenPricesByTokenAddress, batch) => {\n const tokenPricesByTokenAddressForBatch =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: batch,\n chainId,\n currency: nativeCurrency,\n });\n\n return {\n ...allTokenPricesByTokenAddress,\n ...tokenPricesByTokenAddressForBatch,\n };\n },\n initialResult: {},\n });\n contractNativeInformations = tokenPricesByTokenAddress;\n\n // fetch for native token\n if (tokenAddresses.length === 0) {\n const contractNativeInformationsNative =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: [],\n chainId,\n currency: nativeCurrency,\n });\n\n contractNativeInformations = {\n [getNativeTokenAddress(chainId)]: {\n currency: nativeCurrency,\n ...contractNativeInformationsNative[getNativeTokenAddress(chainId)],\n },\n };\n }\n return Object.entries(contractNativeInformations).reduce(\n (obj, [tokenAddress, token]) => {\n obj = {\n ...obj,\n [tokenAddress]: { ...token },\n };\n\n return obj;\n },\n {},\n );\n }\n\n /**\n * If the price API does not support a given native currency, then we need to\n * convert it to a fallback currency and feed that currency into the price\n * API, then convert the prices to our desired native currency.\n *\n * @param args - The arguments to this function.\n * @param args.chainId - The chain id to fetch prices for.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n chainId,\n tokenAddresses,\n nativeCurrency,\n }: {\n chainId: Hex;\n tokenAddresses: Hex[];\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n const [\n contractExchangeInformations,\n fallbackCurrencyToNativeCurrencyConversionRate,\n ] = await Promise.all([\n this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency: FALL_BACK_VS_CURRENCY,\n }),\n getCurrencyConversionRate({\n from: FALL_BACK_VS_CURRENCY,\n to: nativeCurrency,\n }),\n ]);\n\n if (fallbackCurrencyToNativeCurrencyConversionRate === null) {\n return {};\n }\n\n // Converts the price in the fallback currency to the native currency\n const convertFallbackToNative = (value: number | undefined) =>\n value !== undefined && value !== null\n ? value * fallbackCurrencyToNativeCurrencyConversionRate\n : undefined;\n\n const updatedContractExchangeRates = Object.entries(\n contractExchangeInformations,\n ).reduce((acc, [tokenAddress, token]) => {\n acc = {\n ...acc,\n [tokenAddress]: {\n ...token,\n currency: nativeCurrency,\n price: convertFallbackToNative(token.price),\n marketCap: convertFallbackToNative(token.marketCap),\n allTimeHigh: convertFallbackToNative(token.allTimeHigh),\n allTimeLow: convertFallbackToNative(token.allTimeLow),\n totalVolume: convertFallbackToNative(token.totalVolume),\n high1d: convertFallbackToNative(token.high1d),\n low1d: convertFallbackToNative(token.low1d),\n dilutedMarketCap: convertFallbackToNative(token.dilutedMarketCap),\n },\n };\n return acc;\n }, {});\n\n return updatedContractExchangeRates;\n }\n\n /**\n * Reset the controller state to the default state.\n */\n resetState() {\n this.update(() => {\n return getDefaultTokenRatesControllerState();\n });\n }\n}\n\nexport default TokenRatesController;\n"]}
@@ -105,7 +105,10 @@ export type TokenRatesControllerMessenger = RestrictedMessenger<typeof controlle
105
105
  export declare const getDefaultTokenRatesControllerState: () => TokenRatesControllerState;
106
106
  /** The input to start polling for the {@link TokenRatesController} */
107
107
  export type TokenRatesPollingInput = {
108
- chainId: Hex;
108
+ chainIdAndNativeCurrency: {
109
+ chainId: Hex;
110
+ nativeCurrency: string;
111
+ }[];
109
112
  };
110
113
  declare const TokenRatesController_base: (abstract new (...args: any[]) => {
111
114
  readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
@@ -155,34 +158,46 @@ export declare class TokenRatesController extends TokenRatesController_base<type
155
158
  disable(): void;
156
159
  /**
157
160
  * Start (or restart) polling.
161
+ *
162
+ * @param chainId - The chain ID.
163
+ * @param nativeCurrency - The native currency.
158
164
  */
159
- start(): Promise<void>;
165
+ start(chainId: Hex, nativeCurrency: string): Promise<void>;
160
166
  /**
161
167
  * Stop polling.
162
168
  */
163
169
  stop(): void;
164
170
  /**
165
171
  * Updates exchange rates for all tokens.
172
+ *
173
+ * @param chainIdAndNativeCurrency - The chain ID and native currency.
174
+ */
175
+ updateExchangeRates(chainIdAndNativeCurrency: {
176
+ chainId: Hex;
177
+ nativeCurrency: string;
178
+ }[]): Promise<void>;
179
+ /**
180
+ * Updates exchange rates for all tokens.
181
+ *
182
+ * @param chainIds - The chain IDs.
183
+ * @returns A promise that resolves when all chain updates complete.
166
184
  */
167
- updateExchangeRates(): Promise<void>;
168
185
  /**
169
186
  * Updates exchange rates for all tokens.
170
187
  *
171
- * @param options - The options to fetch exchange rates.
172
- * @param options.chainId - The chain ID.
173
- * @param options.nativeCurrency - The ticker for the chain.
188
+ * @param chainIdAndNativeCurrency - The chain ID and native currency.
174
189
  */
175
- updateExchangeRatesByChainId({ chainId, nativeCurrency, }: {
190
+ updateExchangeRatesByChainId(chainIdAndNativeCurrency: {
176
191
  chainId: Hex;
177
192
  nativeCurrency: string;
178
- }): Promise<void>;
193
+ }[]): Promise<void>;
179
194
  /**
180
195
  * Updates token rates for the given networkClientId
181
196
  *
182
197
  * @param input - The input for the poll.
183
- * @param input.chainId - The chain id to poll token rates on.
198
+ * @param input.chainIdAndNativeCurrency - The chain ids and native currencies to poll token rates on.
184
199
  */
185
- _executePoll({ chainId }: TokenRatesPollingInput): Promise<void>;
200
+ _executePoll({ chainIdAndNativeCurrency, }: TokenRatesPollingInput): Promise<void>;
186
201
  /**
187
202
  * Reset the controller state to the default state.
188
203
  */
@@ -1 +1 @@
1
- {"version":3,"file":"TokenRatesController.d.cts","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TokenRatesController.d.cts","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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"}
@@ -105,7 +105,10 @@ export type TokenRatesControllerMessenger = RestrictedMessenger<typeof controlle
105
105
  export declare const getDefaultTokenRatesControllerState: () => TokenRatesControllerState;
106
106
  /** The input to start polling for the {@link TokenRatesController} */
107
107
  export type TokenRatesPollingInput = {
108
- chainId: Hex;
108
+ chainIdAndNativeCurrency: {
109
+ chainId: Hex;
110
+ nativeCurrency: string;
111
+ }[];
109
112
  };
110
113
  declare const TokenRatesController_base: (abstract new (...args: any[]) => {
111
114
  readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
@@ -155,34 +158,46 @@ export declare class TokenRatesController extends TokenRatesController_base<type
155
158
  disable(): void;
156
159
  /**
157
160
  * Start (or restart) polling.
161
+ *
162
+ * @param chainId - The chain ID.
163
+ * @param nativeCurrency - The native currency.
158
164
  */
159
- start(): Promise<void>;
165
+ start(chainId: Hex, nativeCurrency: string): Promise<void>;
160
166
  /**
161
167
  * Stop polling.
162
168
  */
163
169
  stop(): void;
164
170
  /**
165
171
  * Updates exchange rates for all tokens.
172
+ *
173
+ * @param chainIdAndNativeCurrency - The chain ID and native currency.
174
+ */
175
+ updateExchangeRates(chainIdAndNativeCurrency: {
176
+ chainId: Hex;
177
+ nativeCurrency: string;
178
+ }[]): Promise<void>;
179
+ /**
180
+ * Updates exchange rates for all tokens.
181
+ *
182
+ * @param chainIds - The chain IDs.
183
+ * @returns A promise that resolves when all chain updates complete.
166
184
  */
167
- updateExchangeRates(): Promise<void>;
168
185
  /**
169
186
  * Updates exchange rates for all tokens.
170
187
  *
171
- * @param options - The options to fetch exchange rates.
172
- * @param options.chainId - The chain ID.
173
- * @param options.nativeCurrency - The ticker for the chain.
188
+ * @param chainIdAndNativeCurrency - The chain ID and native currency.
174
189
  */
175
- updateExchangeRatesByChainId({ chainId, nativeCurrency, }: {
190
+ updateExchangeRatesByChainId(chainIdAndNativeCurrency: {
176
191
  chainId: Hex;
177
192
  nativeCurrency: string;
178
- }): Promise<void>;
193
+ }[]): Promise<void>;
179
194
  /**
180
195
  * Updates token rates for the given networkClientId
181
196
  *
182
197
  * @param input - The input for the poll.
183
- * @param input.chainId - The chain id to poll token rates on.
198
+ * @param input.chainIdAndNativeCurrency - The chain ids and native currencies to poll token rates on.
184
199
  */
185
- _executePoll({ chainId }: TokenRatesPollingInput): Promise<void>;
200
+ _executePoll({ chainIdAndNativeCurrency, }: TokenRatesPollingInput): Promise<void>;
186
201
  /**
187
202
  * Reset the controller state to the default state.
188
203
  */
@@ -1 +1 @@
1
- {"version":3,"file":"TokenRatesController.d.mts","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TokenRatesController.d.mts","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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"}
@@ -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 _TokenRatesController_instances, _TokenRatesController_handle, _TokenRatesController_pollState, _TokenRatesController_tokenPricesService, _TokenRatesController_inProcessExchangeRateUpdates, _TokenRatesController_selectedAccountId, _TokenRatesController_disabled, _TokenRatesController_chainId, _TokenRatesController_ticker, _TokenRatesController_interval, _TokenRatesController_allTokens, _TokenRatesController_allDetectedTokens, _TokenRatesController_subscribeToTokensStateChange, _TokenRatesController_subscribeToNetworkStateChange, _TokenRatesController_getTokenAddresses, _TokenRatesController_getSelectedAccount, _TokenRatesController_getChainIdAndTicker, _TokenRatesController_getTokensControllerState, _TokenRatesController_stopPoll, _TokenRatesController_poll, _TokenRatesController_fetchAndMapExchangeRates, _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency, _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency;
12
+ var _TokenRatesController_instances, _TokenRatesController_handle, _TokenRatesController_pollState, _TokenRatesController_tokenPricesService, _TokenRatesController_inProcessExchangeRateUpdates, _TokenRatesController_disabled, _TokenRatesController_interval, _TokenRatesController_allTokens, _TokenRatesController_allDetectedTokens, _TokenRatesController_subscribeToTokensStateChange, _TokenRatesController_subscribeToNetworkStateChange, _TokenRatesController_getTokenAddresses, _TokenRatesController_getTokensControllerState, _TokenRatesController_stopPoll, _TokenRatesController_poll, _TokenRatesController_fetchAndMapExchangeRates, _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency, _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency;
13
13
  import { safelyExecute, toChecksumHexAddress, FALL_BACK_VS_CURRENCY } from "@metamask/controller-utils";
14
14
  import { StaticIntervalPollingController } from "@metamask/polling-controller";
15
15
  import { createDeferredPromise } from "@metamask/utils";
@@ -93,10 +93,7 @@ export class TokenRatesController extends StaticIntervalPollingController() {
93
93
  _TokenRatesController_pollState.set(this, PollState.Inactive);
94
94
  _TokenRatesController_tokenPricesService.set(this, void 0);
95
95
  _TokenRatesController_inProcessExchangeRateUpdates.set(this, {});
96
- _TokenRatesController_selectedAccountId.set(this, void 0);
97
96
  _TokenRatesController_disabled.set(this, void 0);
98
- _TokenRatesController_chainId.set(this, void 0);
99
- _TokenRatesController_ticker.set(this, void 0);
100
97
  _TokenRatesController_interval.set(this, void 0);
101
98
  _TokenRatesController_allTokens.set(this, void 0);
102
99
  _TokenRatesController_allDetectedTokens.set(this, void 0);
@@ -104,10 +101,6 @@ export class TokenRatesController extends StaticIntervalPollingController() {
104
101
  __classPrivateFieldSet(this, _TokenRatesController_tokenPricesService, tokenPricesService, "f");
105
102
  __classPrivateFieldSet(this, _TokenRatesController_disabled, disabled, "f");
106
103
  __classPrivateFieldSet(this, _TokenRatesController_interval, interval, "f");
107
- const { chainId: currentChainId, ticker: currentTicker } = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getChainIdAndTicker).call(this);
108
- __classPrivateFieldSet(this, _TokenRatesController_chainId, currentChainId, "f");
109
- __classPrivateFieldSet(this, _TokenRatesController_ticker, currentTicker, "f");
110
- __classPrivateFieldSet(this, _TokenRatesController_selectedAccountId, __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getSelectedAccount).call(this).id, "f");
111
104
  const { allTokens, allDetectedTokens } = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getTokensControllerState).call(this);
112
105
  __classPrivateFieldSet(this, _TokenRatesController_allTokens, allTokens, "f");
113
106
  __classPrivateFieldSet(this, _TokenRatesController_allDetectedTokens, allDetectedTokens, "f");
@@ -128,11 +121,14 @@ export class TokenRatesController extends StaticIntervalPollingController() {
128
121
  }
129
122
  /**
130
123
  * Start (or restart) polling.
124
+ *
125
+ * @param chainId - The chain ID.
126
+ * @param nativeCurrency - The native currency.
131
127
  */
132
- async start() {
128
+ async start(chainId, nativeCurrency) {
133
129
  __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_stopPoll).call(this);
134
130
  __classPrivateFieldSet(this, _TokenRatesController_pollState, PollState.Active, "f");
135
- await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this);
131
+ await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this, chainId, nativeCurrency);
136
132
  }
137
133
  /**
138
134
  * Stop polling.
@@ -143,83 +139,91 @@ export class TokenRatesController extends StaticIntervalPollingController() {
143
139
  }
144
140
  /**
145
141
  * Updates exchange rates for all tokens.
142
+ *
143
+ * @param chainIdAndNativeCurrency - The chain ID and native currency.
146
144
  */
147
- async updateExchangeRates() {
148
- await this.updateExchangeRatesByChainId({
149
- chainId: __classPrivateFieldGet(this, _TokenRatesController_chainId, "f"),
150
- nativeCurrency: __classPrivateFieldGet(this, _TokenRatesController_ticker, "f"),
151
- });
145
+ async updateExchangeRates(chainIdAndNativeCurrency) {
146
+ await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);
152
147
  }
153
148
  /**
154
149
  * Updates exchange rates for all tokens.
155
150
  *
156
- * @param options - The options to fetch exchange rates.
157
- * @param options.chainId - The chain ID.
158
- * @param options.nativeCurrency - The ticker for the chain.
151
+ * @param chainIds - The chain IDs.
152
+ * @returns A promise that resolves when all chain updates complete.
153
+ */
154
+ /**
155
+ * Updates exchange rates for all tokens.
156
+ *
157
+ * @param chainIdAndNativeCurrency - The chain ID and native currency.
159
158
  */
160
- async updateExchangeRatesByChainId({ chainId, nativeCurrency, }) {
159
+ async updateExchangeRatesByChainId(chainIdAndNativeCurrency) {
161
160
  if (__classPrivateFieldGet(this, _TokenRatesController_disabled, "f")) {
162
161
  return;
163
162
  }
164
- const tokenAddresses = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getTokenAddresses).call(this, chainId);
165
- // Key dependencies that will trigger a new request instead of aborting:
166
- // - chainId - different chains require a new request
167
- // - nativeCurrency - changing native currency requires fetching different rates
168
- // - tokenAddress length - if we have detected any new tokens, we will need to make a new request for the rates
169
- const updateKey = `${chainId}:${nativeCurrency}:${tokenAddresses.length}`;
170
- if (updateKey in __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")) {
171
- // This prevents redundant updates
172
- // This promise is resolved after the in-progress update has finished,
173
- // and state has been updated.
174
- await __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
175
- return;
176
- }
177
- const { promise: inProgressUpdate, resolve: updateSucceeded, reject: updateFailed, } = createDeferredPromise({ suppressUnhandledRejection: true });
178
- __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey] = inProgressUpdate;
179
- try {
180
- const contractInformations = await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRates).call(this, {
181
- tokenAddresses,
182
- chainId,
183
- nativeCurrency,
184
- });
185
- const marketData = {
186
- [chainId]: {
187
- ...(contractInformations ?? {}),
188
- },
189
- };
163
+ // Create a promise for each chainId to fetch exchange rates.
164
+ const updatePromises = chainIdAndNativeCurrency.map(async ({ chainId, nativeCurrency }) => {
165
+ const tokenAddresses = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getTokenAddresses).call(this, chainId);
166
+ // Build a unique key based on chainId, nativeCurrency, and the number of token addresses.
167
+ const updateKey = `${chainId}:${nativeCurrency}:${tokenAddresses.length}`;
168
+ if (updateKey in __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")) {
169
+ // Await any ongoing update to avoid redundant work.
170
+ await __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
171
+ return null;
172
+ }
173
+ // Create a deferred promise to track this update.
174
+ const { promise: inProgressUpdate, resolve: updateSucceeded, reject: updateFailed, } = createDeferredPromise({ suppressUnhandledRejection: true });
175
+ __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey] = inProgressUpdate;
176
+ try {
177
+ const contractInformations = await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRates).call(this, {
178
+ tokenAddresses,
179
+ chainId,
180
+ nativeCurrency,
181
+ });
182
+ // Each promise returns an object with the market data for the chain.
183
+ const marketData = {
184
+ [chainId]: {
185
+ ...(contractInformations ?? {}),
186
+ },
187
+ };
188
+ updateSucceeded();
189
+ return marketData;
190
+ }
191
+ catch (error) {
192
+ updateFailed(error);
193
+ throw error;
194
+ }
195
+ finally {
196
+ // Cleanup the tracking for this update.
197
+ delete __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
198
+ }
199
+ });
200
+ // Wait for all update promises to settle.
201
+ const results = await Promise.allSettled(updatePromises);
202
+ // Merge all successful market data updates into one object.
203
+ const combinedMarketData = results.reduce((acc, result) => {
204
+ if (result.status === 'fulfilled' && result.value) {
205
+ acc = { ...acc, ...result.value };
206
+ }
207
+ return acc;
208
+ }, {});
209
+ // Call this.update only once with the combined market data to reduce the number of state changes and re-renders
210
+ if (Object.keys(combinedMarketData).length > 0) {
190
211
  this.update((state) => {
191
212
  state.marketData = {
192
213
  ...state.marketData,
193
- ...marketData,
214
+ ...combinedMarketData,
194
215
  };
195
216
  });
196
- updateSucceeded();
197
- }
198
- catch (error) {
199
- updateFailed(error);
200
- throw error;
201
- }
202
- finally {
203
- delete __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
204
217
  }
205
218
  }
206
219
  /**
207
220
  * Updates token rates for the given networkClientId
208
221
  *
209
222
  * @param input - The input for the poll.
210
- * @param input.chainId - The chain id to poll token rates on.
223
+ * @param input.chainIdAndNativeCurrency - The chain ids and native currencies to poll token rates on.
211
224
  */
212
- async _executePoll({ chainId }) {
213
- const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
214
- const networkConfiguration = networkConfigurationsByChainId[chainId];
215
- if (!networkConfiguration) {
216
- console.error(`TokenRatesController: No network configuration found for chainId ${chainId}`);
217
- return;
218
- }
219
- await this.updateExchangeRatesByChainId({
220
- chainId,
221
- nativeCurrency: networkConfiguration.nativeCurrency,
222
- });
225
+ async _executePoll({ chainIdAndNativeCurrency, }) {
226
+ await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);
223
227
  }
224
228
  /**
225
229
  * Reset the controller state to the default state.
@@ -230,7 +234,7 @@ export class TokenRatesController extends StaticIntervalPollingController() {
230
234
  });
231
235
  }
232
236
  }
233
- _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState = new WeakMap(), _TokenRatesController_tokenPricesService = new WeakMap(), _TokenRatesController_inProcessExchangeRateUpdates = new WeakMap(), _TokenRatesController_selectedAccountId = new WeakMap(), _TokenRatesController_disabled = new WeakMap(), _TokenRatesController_chainId = new WeakMap(), _TokenRatesController_ticker = new WeakMap(), _TokenRatesController_interval = new WeakMap(), _TokenRatesController_allTokens = new WeakMap(), _TokenRatesController_allDetectedTokens = new WeakMap(), _TokenRatesController_instances = new WeakSet(), _TokenRatesController_subscribeToTokensStateChange = function _TokenRatesController_subscribeToTokensStateChange() {
237
+ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState = new WeakMap(), _TokenRatesController_tokenPricesService = new WeakMap(), _TokenRatesController_inProcessExchangeRateUpdates = new WeakMap(), _TokenRatesController_disabled = new WeakMap(), _TokenRatesController_interval = new WeakMap(), _TokenRatesController_allTokens = new WeakMap(), _TokenRatesController_allDetectedTokens = new WeakMap(), _TokenRatesController_instances = new WeakSet(), _TokenRatesController_subscribeToTokensStateChange = function _TokenRatesController_subscribeToTokensStateChange() {
234
238
  this.messagingSystem.subscribe('TokensController:stateChange',
235
239
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
236
240
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
@@ -238,6 +242,7 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
238
242
  if (__classPrivateFieldGet(this, _TokenRatesController_disabled, "f")) {
239
243
  return;
240
244
  }
245
+ const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
241
246
  const chainIds = [
242
247
  ...new Set([
243
248
  ...Object.keys(allTokens),
@@ -248,16 +253,13 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
248
253
  !isEqual(__classPrivateFieldGet(this, _TokenRatesController_allDetectedTokens, "f")[chainId], allDetectedTokens[chainId]));
249
254
  __classPrivateFieldSet(this, _TokenRatesController_allTokens, allTokens, "f");
250
255
  __classPrivateFieldSet(this, _TokenRatesController_allDetectedTokens, allDetectedTokens, "f");
251
- const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
252
- await Promise.allSettled(chainIdsToUpdate.map(async (chainId) => {
253
- const nativeCurrency = networkConfigurationsByChainId[chainId]?.nativeCurrency;
254
- if (nativeCurrency) {
255
- await this.updateExchangeRatesByChainId({
256
- chainId: chainId,
257
- nativeCurrency,
258
- });
259
- }
260
- }));
256
+ const chainIdAndNativeCurrency = chainIdsToUpdate.map((chainId) => {
257
+ return {
258
+ chainId: chainId,
259
+ nativeCurrency: networkConfigurationsByChainId[chainId]?.nativeCurrency,
260
+ };
261
+ });
262
+ await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);
261
263
  }, ({ allTokens, allDetectedTokens }) => {
262
264
  return { allTokens, allDetectedTokens };
263
265
  });
@@ -265,14 +267,15 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
265
267
  this.messagingSystem.subscribe('NetworkController:stateChange',
266
268
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
267
269
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
268
- async ({ selectedNetworkClientId }, patches) => {
269
- const { configuration: { chainId, ticker }, } = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
270
- if (__classPrivateFieldGet(this, _TokenRatesController_chainId, "f") !== chainId || __classPrivateFieldGet(this, _TokenRatesController_ticker, "f") !== ticker) {
271
- __classPrivateFieldSet(this, _TokenRatesController_chainId, chainId, "f");
272
- __classPrivateFieldSet(this, _TokenRatesController_ticker, ticker, "f");
273
- if (__classPrivateFieldGet(this, _TokenRatesController_pollState, "f") === PollState.Active) {
274
- await this.updateExchangeRates();
275
- }
270
+ async ({ networkConfigurationsByChainId }, patches) => {
271
+ const chainIdAndNativeCurrency = Object.values(networkConfigurationsByChainId).map(({ chainId, nativeCurrency }) => {
272
+ return {
273
+ chainId: chainId,
274
+ nativeCurrency,
275
+ };
276
+ });
277
+ if (__classPrivateFieldGet(this, _TokenRatesController_pollState, "f") === PollState.Active) {
278
+ await this.updateExchangeRates(chainIdAndNativeCurrency);
276
279
  }
277
280
  // Remove state for deleted networks
278
281
  for (const patch of patches) {
@@ -290,16 +293,6 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
290
293
  const tokenAddresses = getTokens(__classPrivateFieldGet(this, _TokenRatesController_allTokens, "f")[chainId]);
291
294
  const detectedTokenAddresses = getTokens(__classPrivateFieldGet(this, _TokenRatesController_allDetectedTokens, "f")[chainId]);
292
295
  return [...new Set([...tokenAddresses, ...detectedTokenAddresses])].sort();
293
- }, _TokenRatesController_getSelectedAccount = function _TokenRatesController_getSelectedAccount() {
294
- const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
295
- return selectedAccount;
296
- }, _TokenRatesController_getChainIdAndTicker = function _TokenRatesController_getChainIdAndTicker() {
297
- const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
298
- const networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
299
- return {
300
- chainId: networkClient.configuration.chainId,
301
- ticker: networkClient.configuration.ticker,
302
- };
303
296
  }, _TokenRatesController_getTokensControllerState = function _TokenRatesController_getTokensControllerState() {
304
297
  const { allTokens, allDetectedTokens } = this.messagingSystem.call('TokensController:getState');
305
298
  return {
@@ -313,15 +306,18 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
313
306
  }, _TokenRatesController_poll =
314
307
  /**
315
308
  * Poll for exchange rate updates.
309
+ *
310
+ * @param chainId - The chain ID.
311
+ * @param nativeCurrency - The native currency.
316
312
  */
317
- async function _TokenRatesController_poll() {
318
- await safelyExecute(() => this.updateExchangeRates());
313
+ async function _TokenRatesController_poll(chainId, nativeCurrency) {
314
+ await safelyExecute(() => this.updateExchangeRates([{ chainId, nativeCurrency }]));
319
315
  // Poll using recursive `setTimeout` instead of `setInterval` so that
320
316
  // requests don't stack if they take longer than the polling interval
321
317
  __classPrivateFieldSet(this, _TokenRatesController_handle, setTimeout(() => {
322
318
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
323
319
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
324
- __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this);
320
+ __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this, chainId, nativeCurrency);
325
321
  }, __classPrivateFieldGet(this, _TokenRatesController_interval, "f")), "f");
326
322
  }, _TokenRatesController_fetchAndMapExchangeRates =
327
323
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TokenRatesController.mjs","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerGetAccountAction,\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n safelyExecute,\n toChecksumHexAddress,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerStateChangeEvent,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { createDeferredPromise, type Hex } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport { reduceInBatchesSerially, TOKEN_PRICES_BATCH_SIZE } from './assetsUtil';\nimport { fetchExchangeRate as fetchNativeCurrencyExchangeRate } from './crypto-compare-service';\nimport type { AbstractTokenPricesService } from './token-prices-service/abstract-token-prices-service';\nimport { getNativeTokenAddress } from './token-prices-service/codefi-v2';\nimport type {\n TokensControllerGetStateAction,\n TokensControllerStateChangeEvent,\n TokensControllerState,\n} from './TokensController';\n\n/**\n * @type Token\n *\n * Token representation\n * @property address - Hex address of the token contract\n * @property decimals - Number of decimals the token uses\n * @property symbol - Symbol of the token\n * @property aggregators - An array containing the token's aggregators\n * @property image - Image of the token, url or bit32 image\n * @property hasBalanceError - 'true' if there is an error while updating the token balance\n * @property isERC721 - 'true' if the token is a ERC721 token\n * @property name - Name of the token\n */\nexport type Token = {\n address: string;\n decimals: number;\n symbol: string;\n aggregators?: string[];\n image?: string;\n hasBalanceError?: boolean;\n isERC721?: boolean;\n name?: string;\n};\n\nconst DEFAULT_INTERVAL = 180000;\n\nexport type ContractExchangeRates = {\n [address: string]: number | undefined;\n};\n\nexport type MarketDataDetails = {\n tokenAddress: `0x${string}`;\n currency: string;\n allTimeHigh: number;\n allTimeLow: number;\n circulatingSupply: number;\n dilutedMarketCap: number;\n high1d: number;\n low1d: number;\n marketCap: number;\n marketCapPercentChange1d: number;\n price: number;\n priceChange1d: number;\n pricePercentChange1d: number;\n pricePercentChange1h: number;\n pricePercentChange1y: number;\n pricePercentChange7d: number;\n pricePercentChange14d: number;\n pricePercentChange30d: number;\n pricePercentChange200d: number;\n totalVolume: number;\n};\n\n/**\n * Represents a mapping of token contract addresses to their market data.\n */\nexport type ContractMarketData = Record<Hex, MarketDataDetails>;\n\nenum PollState {\n Active = 'Active',\n Inactive = 'Inactive',\n}\n\n/**\n * The external actions available to the {@link TokenRatesController}.\n */\nexport type AllowedActions =\n | TokensControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | AccountsControllerGetAccountAction\n | AccountsControllerGetSelectedAccountAction;\n\n/**\n * The external events available to the {@link TokenRatesController}.\n */\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | NetworkControllerStateChangeEvent\n | AccountsControllerSelectedEvmAccountChangeEvent;\n\n/**\n * The name of the {@link TokenRatesController}.\n */\nexport const controllerName = 'TokenRatesController';\n\n/**\n * @type TokenRatesState\n *\n * Token rates controller state\n * @property marketData - Market data for tokens, keyed by chain ID and then token contract address.\n */\nexport type TokenRatesControllerState = {\n marketData: Record<Hex, Record<Hex, MarketDataDetails>>;\n};\n\n/**\n * The action that can be performed to get the state of the {@link TokenRatesController}.\n */\nexport type TokenRatesControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TokenRatesControllerState\n>;\n\n/**\n * The actions that can be performed using the {@link TokenRatesController}.\n */\nexport type TokenRatesControllerActions = TokenRatesControllerGetStateAction;\n\n/**\n * The event that {@link TokenRatesController} can emit.\n */\nexport type TokenRatesControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n TokenRatesControllerState\n>;\n\n/**\n * The events that {@link TokenRatesController} can emit.\n */\nexport type TokenRatesControllerEvents = TokenRatesControllerStateChangeEvent;\n\n/**\n * The messenger of the {@link TokenRatesController} for communication.\n */\nexport type TokenRatesControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n TokenRatesControllerActions | AllowedActions,\n TokenRatesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Uses the CryptoCompare API to fetch the exchange rate between one currency\n * and another, i.e., the multiplier to apply the amount of one currency in\n * order to convert it to another.\n *\n * @param args - The arguments to this function.\n * @param args.from - The currency to convert from.\n * @param args.to - The currency to convert to.\n * @returns The exchange rate between `fromCurrency` to `toCurrency` if one\n * exists, or null if one does not.\n */\nasync function getCurrencyConversionRate({\n from,\n to,\n}: {\n from: string;\n to: string;\n}) {\n const includeUSDRate = false;\n try {\n const result = await fetchNativeCurrencyExchangeRate(\n to,\n from,\n includeUSDRate,\n );\n return result.conversionRate;\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n ) {\n return null;\n }\n throw error;\n }\n}\n\nconst tokenRatesControllerMetadata = {\n marketData: { persist: true, anonymous: false },\n};\n\n/**\n * Get the default {@link TokenRatesController} state.\n *\n * @returns The default {@link TokenRatesController} state.\n */\nexport const getDefaultTokenRatesControllerState =\n (): TokenRatesControllerState => {\n return {\n marketData: {},\n };\n };\n\n/** The input to start polling for the {@link TokenRatesController} */\nexport type TokenRatesPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval for token-to-fiat exchange rates\n * for tokens stored in the TokensController\n */\nexport class TokenRatesController extends StaticIntervalPollingController<TokenRatesPollingInput>()<\n typeof controllerName,\n TokenRatesControllerState,\n TokenRatesControllerMessenger\n> {\n #handle?: ReturnType<typeof setTimeout>;\n\n #pollState = PollState.Inactive;\n\n readonly #tokenPricesService: AbstractTokenPricesService;\n\n #inProcessExchangeRateUpdates: Record<`${Hex}:${string}`, Promise<void>> = {};\n\n #selectedAccountId: string;\n\n #disabled: boolean;\n\n #chainId: Hex;\n\n #ticker: string;\n\n #interval: number;\n\n #allTokens: TokensControllerState['allTokens'];\n\n #allDetectedTokens: TokensControllerState['allDetectedTokens'];\n\n /**\n * Creates a TokenRatesController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The polling interval in ms\n * @param options.disabled - Boolean to track if network requests are blocked\n * @param options.tokenPricesService - An object in charge of retrieving token price\n * @param options.messenger - The messenger instance for communication\n * @param options.state - Initial state to set on this controller\n */\n constructor({\n interval = DEFAULT_INTERVAL,\n disabled = false,\n tokenPricesService,\n messenger,\n state,\n }: {\n interval?: number;\n disabled?: boolean;\n tokenPricesService: AbstractTokenPricesService;\n messenger: TokenRatesControllerMessenger;\n state?: Partial<TokenRatesControllerState>;\n }) {\n super({\n name: controllerName,\n messenger,\n state: { ...getDefaultTokenRatesControllerState(), ...state },\n metadata: tokenRatesControllerMetadata,\n });\n\n this.setIntervalLength(interval);\n this.#tokenPricesService = tokenPricesService;\n this.#disabled = disabled;\n this.#interval = interval;\n\n const { chainId: currentChainId, ticker: currentTicker } =\n this.#getChainIdAndTicker();\n this.#chainId = currentChainId;\n this.#ticker = currentTicker;\n\n this.#selectedAccountId = this.#getSelectedAccount().id;\n\n const { allTokens, allDetectedTokens } = this.#getTokensControllerState();\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n this.#subscribeToTokensStateChange();\n\n this.#subscribeToNetworkStateChange();\n }\n\n #subscribeToTokensStateChange() {\n this.messagingSystem.subscribe(\n 'TokensController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async ({ allTokens, allDetectedTokens }) => {\n if (this.#disabled) {\n return;\n }\n\n const chainIds = [\n ...new Set([\n ...Object.keys(allTokens),\n ...Object.keys(allDetectedTokens),\n ]),\n ] as Hex[];\n\n const chainIdsToUpdate = chainIds.filter(\n (chainId) =>\n !isEqual(this.#allTokens[chainId], allTokens[chainId]) ||\n !isEqual(\n this.#allDetectedTokens[chainId],\n allDetectedTokens[chainId],\n ),\n );\n\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n\n await Promise.allSettled(\n chainIdsToUpdate.map(async (chainId) => {\n const nativeCurrency =\n networkConfigurationsByChainId[chainId as Hex]?.nativeCurrency;\n\n if (nativeCurrency) {\n await this.updateExchangeRatesByChainId({\n chainId: chainId as Hex,\n nativeCurrency,\n });\n }\n }),\n );\n },\n ({ allTokens, allDetectedTokens }) => {\n return { allTokens, allDetectedTokens };\n },\n );\n }\n\n #subscribeToNetworkStateChange() {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async ({ selectedNetworkClientId }, patches) => {\n const {\n configuration: { chainId, ticker },\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n if (this.#chainId !== chainId || this.#ticker !== ticker) {\n this.#chainId = chainId;\n this.#ticker = ticker;\n if (this.#pollState === PollState.Active) {\n await this.updateExchangeRates();\n }\n }\n\n // Remove state for deleted networks\n for (const patch of patches) {\n if (\n patch.op === 'remove' &&\n patch.path[0] === 'networkConfigurationsByChainId'\n ) {\n const removedChainId = patch.path[1] as Hex;\n this.update((state) => {\n delete state.marketData[removedChainId];\n });\n }\n }\n },\n );\n }\n\n /**\n * Get the tokens for the given chain.\n *\n * @param chainId - The chain ID.\n * @returns The list of tokens addresses for the current chain\n */\n #getTokenAddresses(chainId: Hex): Hex[] {\n const getTokens = (allTokens: Record<Hex, { address: string }[]>) =>\n Object.values(allTokens ?? {}).flatMap((tokens) =>\n tokens.map(({ address }) => toChecksumHexAddress(address) as Hex),\n );\n\n const tokenAddresses = getTokens(this.#allTokens[chainId]);\n const detectedTokenAddresses = getTokens(this.#allDetectedTokens[chainId]);\n\n return [...new Set([...tokenAddresses, ...detectedTokenAddresses])].sort();\n }\n\n /**\n * Allows controller to make active and passive polling requests\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Blocks controller from making network calls\n */\n disable(): void {\n this.#disabled = true;\n }\n\n /**\n * Start (or restart) polling.\n */\n async start() {\n this.#stopPoll();\n this.#pollState = PollState.Active;\n await this.#poll();\n }\n\n /**\n * Stop polling.\n */\n stop() {\n this.#stopPoll();\n this.#pollState = PollState.Inactive;\n }\n\n #getSelectedAccount(): InternalAccount {\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n\n return selectedAccount;\n }\n\n #getChainIdAndTicker(): {\n chainId: Hex;\n ticker: string;\n } {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return {\n chainId: networkClient.configuration.chainId,\n ticker: networkClient.configuration.ticker,\n };\n }\n\n #getTokensControllerState(): {\n allTokens: TokensControllerState['allTokens'];\n allDetectedTokens: TokensControllerState['allDetectedTokens'];\n } {\n const { allTokens, allDetectedTokens } = this.messagingSystem.call(\n 'TokensController:getState',\n );\n\n return {\n allTokens,\n allDetectedTokens,\n };\n }\n\n /**\n * Clear the active polling timer, if present.\n */\n #stopPoll() {\n if (this.#handle) {\n clearTimeout(this.#handle);\n }\n }\n\n /**\n * Poll for exchange rate updates.\n */\n async #poll() {\n await safelyExecute(() => this.updateExchangeRates());\n\n // Poll using recursive `setTimeout` instead of `setInterval` so that\n // requests don't stack if they take longer than the polling interval\n this.#handle = setTimeout(() => {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#poll();\n }, this.#interval);\n }\n\n /**\n * Updates exchange rates for all tokens.\n */\n async updateExchangeRates() {\n await this.updateExchangeRatesByChainId({\n chainId: this.#chainId,\n nativeCurrency: this.#ticker,\n });\n }\n\n /**\n * Updates exchange rates for all tokens.\n *\n * @param options - The options to fetch exchange rates.\n * @param options.chainId - The chain ID.\n * @param options.nativeCurrency - The ticker for the chain.\n */\n async updateExchangeRatesByChainId({\n chainId,\n nativeCurrency,\n }: {\n chainId: Hex;\n nativeCurrency: string;\n }) {\n if (this.#disabled) {\n return;\n }\n\n const tokenAddresses = this.#getTokenAddresses(chainId);\n\n // Key dependencies that will trigger a new request instead of aborting:\n // - chainId - different chains require a new request\n // - nativeCurrency - changing native currency requires fetching different rates\n // - tokenAddress length - if we have detected any new tokens, we will need to make a new request for the rates\n const updateKey: `${Hex}:${string}` = `${chainId}:${nativeCurrency}:${tokenAddresses.length}`;\n if (updateKey in this.#inProcessExchangeRateUpdates) {\n // This prevents redundant updates\n // This promise is resolved after the in-progress update has finished,\n // and state has been updated.\n await this.#inProcessExchangeRateUpdates[updateKey];\n return;\n }\n\n const {\n promise: inProgressUpdate,\n resolve: updateSucceeded,\n reject: updateFailed,\n } = createDeferredPromise({ suppressUnhandledRejection: true });\n this.#inProcessExchangeRateUpdates[updateKey] = inProgressUpdate;\n\n try {\n const contractInformations = await this.#fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n\n const marketData = {\n [chainId]: {\n ...(contractInformations ?? {}),\n },\n };\n\n this.update((state) => {\n state.marketData = {\n ...state.marketData,\n ...marketData,\n };\n });\n updateSucceeded();\n } catch (error: unknown) {\n updateFailed(error);\n throw error;\n } finally {\n delete this.#inProcessExchangeRateUpdates[updateKey];\n }\n }\n\n /**\n * Uses the token prices service to retrieve exchange rates for tokens in a\n * particular currency.\n *\n * If the price API does not support the given chain ID, returns an empty\n * object.\n *\n * If the price API does not support the given currency, retrieves exchange\n * rates in a known currency instead, then converts those rates using the\n * exchange rate between the known currency and desired currency.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * exchange rates.\n * @returns A map from token address to its exchange rate in the native\n * currency, or an empty map if no exchange rates can be obtained for the\n * chain ID.\n */\n async #fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n if (!this.#tokenPricesService.validateChainIdSupported(chainId)) {\n return tokenAddresses.reduce((obj, tokenAddress) => {\n obj = {\n ...obj,\n [tokenAddress]: undefined,\n };\n\n return obj;\n }, {});\n }\n\n if (this.#tokenPricesService.validateCurrencySupported(nativeCurrency)) {\n return await this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n }\n\n return await this.#fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n chainId,\n tokenAddresses,\n nativeCurrency,\n });\n }\n\n /**\n * Updates token rates for the given networkClientId\n *\n * @param input - The input for the poll.\n * @param input.chainId - The chain id to poll token rates on.\n */\n async _executePoll({ chainId }: TokenRatesPollingInput): Promise<void> {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n\n const networkConfiguration = networkConfigurationsByChainId[chainId];\n if (!networkConfiguration) {\n console.error(\n `TokenRatesController: No network configuration found for chainId ${chainId}`,\n );\n return;\n }\n\n await this.updateExchangeRatesByChainId({\n chainId,\n nativeCurrency: networkConfiguration.nativeCurrency,\n });\n }\n\n /**\n * Retrieves prices in the given currency for the given tokens on the given\n * chain. Ensures that token addresses are checksum addresses.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n let contractNativeInformations;\n const tokenPricesByTokenAddress = await reduceInBatchesSerially<\n Hex,\n Awaited<ReturnType<AbstractTokenPricesService['fetchTokenPrices']>>\n >({\n values: [...tokenAddresses].sort(),\n batchSize: TOKEN_PRICES_BATCH_SIZE,\n eachBatch: async (allTokenPricesByTokenAddress, batch) => {\n const tokenPricesByTokenAddressForBatch =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: batch,\n chainId,\n currency: nativeCurrency,\n });\n\n return {\n ...allTokenPricesByTokenAddress,\n ...tokenPricesByTokenAddressForBatch,\n };\n },\n initialResult: {},\n });\n contractNativeInformations = tokenPricesByTokenAddress;\n\n // fetch for native token\n if (tokenAddresses.length === 0) {\n const contractNativeInformationsNative =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: [],\n chainId,\n currency: nativeCurrency,\n });\n\n contractNativeInformations = {\n [getNativeTokenAddress(chainId)]: {\n currency: nativeCurrency,\n ...contractNativeInformationsNative[getNativeTokenAddress(chainId)],\n },\n };\n }\n return Object.entries(contractNativeInformations).reduce(\n (obj, [tokenAddress, token]) => {\n obj = {\n ...obj,\n [tokenAddress]: { ...token },\n };\n\n return obj;\n },\n {},\n );\n }\n\n /**\n * If the price API does not support a given native currency, then we need to\n * convert it to a fallback currency and feed that currency into the price\n * API, then convert the prices to our desired native currency.\n *\n * @param args - The arguments to this function.\n * @param args.chainId - The chain id to fetch prices for.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n chainId,\n tokenAddresses,\n nativeCurrency,\n }: {\n chainId: Hex;\n tokenAddresses: Hex[];\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n const [\n contractExchangeInformations,\n fallbackCurrencyToNativeCurrencyConversionRate,\n ] = await Promise.all([\n this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency: FALL_BACK_VS_CURRENCY,\n }),\n getCurrencyConversionRate({\n from: FALL_BACK_VS_CURRENCY,\n to: nativeCurrency,\n }),\n ]);\n\n if (fallbackCurrencyToNativeCurrencyConversionRate === null) {\n return {};\n }\n\n // Converts the price in the fallback currency to the native currency\n const convertFallbackToNative = (value: number | undefined) =>\n value !== undefined && value !== null\n ? value * fallbackCurrencyToNativeCurrencyConversionRate\n : undefined;\n\n const updatedContractExchangeRates = Object.entries(\n contractExchangeInformations,\n ).reduce((acc, [tokenAddress, token]) => {\n acc = {\n ...acc,\n [tokenAddress]: {\n ...token,\n currency: nativeCurrency,\n price: convertFallbackToNative(token.price),\n marketCap: convertFallbackToNative(token.marketCap),\n allTimeHigh: convertFallbackToNative(token.allTimeHigh),\n allTimeLow: convertFallbackToNative(token.allTimeLow),\n totalVolume: convertFallbackToNative(token.totalVolume),\n high1d: convertFallbackToNative(token.high1d),\n low1d: convertFallbackToNative(token.low1d),\n dilutedMarketCap: convertFallbackToNative(token.dilutedMarketCap),\n },\n };\n return acc;\n }, {});\n\n return updatedContractExchangeRates;\n }\n\n /**\n * Reset the controller state to the default state.\n */\n resetState() {\n this.update(() => {\n return getDefaultTokenRatesControllerState();\n });\n }\n}\n\nexport default TokenRatesController;\n"]}
1
+ {"version":3,"file":"TokenRatesController.mjs","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerGetAccountAction,\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n safelyExecute,\n toChecksumHexAddress,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerStateChangeEvent,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { createDeferredPromise, type Hex } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport { reduceInBatchesSerially, TOKEN_PRICES_BATCH_SIZE } from './assetsUtil';\nimport { fetchExchangeRate as fetchNativeCurrencyExchangeRate } from './crypto-compare-service';\nimport type { AbstractTokenPricesService } from './token-prices-service/abstract-token-prices-service';\nimport { getNativeTokenAddress } from './token-prices-service/codefi-v2';\nimport type {\n TokensControllerGetStateAction,\n TokensControllerStateChangeEvent,\n TokensControllerState,\n} from './TokensController';\n\n/**\n * @type Token\n *\n * Token representation\n * @property address - Hex address of the token contract\n * @property decimals - Number of decimals the token uses\n * @property symbol - Symbol of the token\n * @property aggregators - An array containing the token's aggregators\n * @property image - Image of the token, url or bit32 image\n * @property hasBalanceError - 'true' if there is an error while updating the token balance\n * @property isERC721 - 'true' if the token is a ERC721 token\n * @property name - Name of the token\n */\nexport type Token = {\n address: string;\n decimals: number;\n symbol: string;\n aggregators?: string[];\n image?: string;\n hasBalanceError?: boolean;\n isERC721?: boolean;\n name?: string;\n};\n\nconst DEFAULT_INTERVAL = 180000;\n\nexport type ContractExchangeRates = {\n [address: string]: number | undefined;\n};\n\nexport type MarketDataDetails = {\n tokenAddress: `0x${string}`;\n currency: string;\n allTimeHigh: number;\n allTimeLow: number;\n circulatingSupply: number;\n dilutedMarketCap: number;\n high1d: number;\n low1d: number;\n marketCap: number;\n marketCapPercentChange1d: number;\n price: number;\n priceChange1d: number;\n pricePercentChange1d: number;\n pricePercentChange1h: number;\n pricePercentChange1y: number;\n pricePercentChange7d: number;\n pricePercentChange14d: number;\n pricePercentChange30d: number;\n pricePercentChange200d: number;\n totalVolume: number;\n};\n\n/**\n * Represents a mapping of token contract addresses to their market data.\n */\nexport type ContractMarketData = Record<Hex, MarketDataDetails>;\n\nenum PollState {\n Active = 'Active',\n Inactive = 'Inactive',\n}\n\n/**\n * The external actions available to the {@link TokenRatesController}.\n */\nexport type AllowedActions =\n | TokensControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | AccountsControllerGetAccountAction\n | AccountsControllerGetSelectedAccountAction;\n\n/**\n * The external events available to the {@link TokenRatesController}.\n */\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | NetworkControllerStateChangeEvent\n | AccountsControllerSelectedEvmAccountChangeEvent;\n\n/**\n * The name of the {@link TokenRatesController}.\n */\nexport const controllerName = 'TokenRatesController';\n\n/**\n * @type TokenRatesState\n *\n * Token rates controller state\n * @property marketData - Market data for tokens, keyed by chain ID and then token contract address.\n */\nexport type TokenRatesControllerState = {\n marketData: Record<Hex, Record<Hex, MarketDataDetails>>;\n};\n\n/**\n * The action that can be performed to get the state of the {@link TokenRatesController}.\n */\nexport type TokenRatesControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TokenRatesControllerState\n>;\n\n/**\n * The actions that can be performed using the {@link TokenRatesController}.\n */\nexport type TokenRatesControllerActions = TokenRatesControllerGetStateAction;\n\n/**\n * The event that {@link TokenRatesController} can emit.\n */\nexport type TokenRatesControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n TokenRatesControllerState\n>;\n\n/**\n * The events that {@link TokenRatesController} can emit.\n */\nexport type TokenRatesControllerEvents = TokenRatesControllerStateChangeEvent;\n\n/**\n * The messenger of the {@link TokenRatesController} for communication.\n */\nexport type TokenRatesControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n TokenRatesControllerActions | AllowedActions,\n TokenRatesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Uses the CryptoCompare API to fetch the exchange rate between one currency\n * and another, i.e., the multiplier to apply the amount of one currency in\n * order to convert it to another.\n *\n * @param args - The arguments to this function.\n * @param args.from - The currency to convert from.\n * @param args.to - The currency to convert to.\n * @returns The exchange rate between `fromCurrency` to `toCurrency` if one\n * exists, or null if one does not.\n */\nasync function getCurrencyConversionRate({\n from,\n to,\n}: {\n from: string;\n to: string;\n}) {\n const includeUSDRate = false;\n try {\n const result = await fetchNativeCurrencyExchangeRate(\n to,\n from,\n includeUSDRate,\n );\n return result.conversionRate;\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n ) {\n return null;\n }\n throw error;\n }\n}\n\nconst tokenRatesControllerMetadata = {\n marketData: { persist: true, anonymous: false },\n};\n\n/**\n * Get the default {@link TokenRatesController} state.\n *\n * @returns The default {@link TokenRatesController} state.\n */\nexport const getDefaultTokenRatesControllerState =\n (): TokenRatesControllerState => {\n return {\n marketData: {},\n };\n };\n\n/** The input to start polling for the {@link TokenRatesController} */\nexport type TokenRatesPollingInput = {\n chainIdAndNativeCurrency: {\n chainId: Hex;\n nativeCurrency: string;\n }[];\n};\n\n/**\n * Controller that passively polls on a set interval for token-to-fiat exchange rates\n * for tokens stored in the TokensController\n */\nexport class TokenRatesController extends StaticIntervalPollingController<TokenRatesPollingInput>()<\n typeof controllerName,\n TokenRatesControllerState,\n TokenRatesControllerMessenger\n> {\n #handle?: ReturnType<typeof setTimeout>;\n\n #pollState = PollState.Inactive;\n\n readonly #tokenPricesService: AbstractTokenPricesService;\n\n #inProcessExchangeRateUpdates: Record<`${Hex}:${string}`, Promise<void>> = {};\n\n #disabled: boolean;\n\n #interval: number;\n\n #allTokens: TokensControllerState['allTokens'];\n\n #allDetectedTokens: TokensControllerState['allDetectedTokens'];\n\n /**\n * Creates a TokenRatesController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The polling interval in ms\n * @param options.disabled - Boolean to track if network requests are blocked\n * @param options.tokenPricesService - An object in charge of retrieving token price\n * @param options.messenger - The messenger instance for communication\n * @param options.state - Initial state to set on this controller\n */\n constructor({\n interval = DEFAULT_INTERVAL,\n disabled = false,\n tokenPricesService,\n messenger,\n state,\n }: {\n interval?: number;\n disabled?: boolean;\n tokenPricesService: AbstractTokenPricesService;\n messenger: TokenRatesControllerMessenger;\n state?: Partial<TokenRatesControllerState>;\n }) {\n super({\n name: controllerName,\n messenger,\n state: { ...getDefaultTokenRatesControllerState(), ...state },\n metadata: tokenRatesControllerMetadata,\n });\n\n this.setIntervalLength(interval);\n this.#tokenPricesService = tokenPricesService;\n this.#disabled = disabled;\n this.#interval = interval;\n\n const { allTokens, allDetectedTokens } = this.#getTokensControllerState();\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n this.#subscribeToTokensStateChange();\n\n this.#subscribeToNetworkStateChange();\n }\n\n #subscribeToTokensStateChange() {\n this.messagingSystem.subscribe(\n 'TokensController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async ({ allTokens, allDetectedTokens }) => {\n if (this.#disabled) {\n return;\n }\n\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n\n const chainIds = [\n ...new Set([\n ...Object.keys(allTokens),\n ...Object.keys(allDetectedTokens),\n ]),\n ] as Hex[];\n\n const chainIdsToUpdate = chainIds.filter(\n (chainId) =>\n !isEqual(this.#allTokens[chainId], allTokens[chainId]) ||\n !isEqual(\n this.#allDetectedTokens[chainId],\n allDetectedTokens[chainId],\n ),\n );\n\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n const chainIdAndNativeCurrency = chainIdsToUpdate.map((chainId) => {\n return {\n chainId: chainId as Hex,\n nativeCurrency:\n networkConfigurationsByChainId[chainId]?.nativeCurrency,\n };\n });\n\n await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);\n },\n ({ allTokens, allDetectedTokens }) => {\n return { allTokens, allDetectedTokens };\n },\n );\n }\n\n #subscribeToNetworkStateChange() {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async ({ networkConfigurationsByChainId }, patches) => {\n const chainIdAndNativeCurrency: {\n chainId: Hex;\n nativeCurrency: string;\n }[] = Object.values(networkConfigurationsByChainId).map(\n ({ chainId, nativeCurrency }) => {\n return {\n chainId: chainId as Hex,\n nativeCurrency,\n };\n },\n );\n\n if (this.#pollState === PollState.Active) {\n await this.updateExchangeRates(chainIdAndNativeCurrency);\n }\n\n // Remove state for deleted networks\n for (const patch of patches) {\n if (\n patch.op === 'remove' &&\n patch.path[0] === 'networkConfigurationsByChainId'\n ) {\n const removedChainId = patch.path[1] as Hex;\n this.update((state) => {\n delete state.marketData[removedChainId];\n });\n }\n }\n },\n );\n }\n\n /**\n * Get the tokens for the given chain.\n *\n * @param chainId - The chain ID.\n * @returns The list of tokens addresses for the current chain\n */\n #getTokenAddresses(chainId: Hex): Hex[] {\n const getTokens = (allTokens: Record<Hex, { address: string }[]>) =>\n Object.values(allTokens ?? {}).flatMap((tokens) =>\n tokens.map(({ address }) => toChecksumHexAddress(address) as Hex),\n );\n\n const tokenAddresses = getTokens(this.#allTokens[chainId]);\n const detectedTokenAddresses = getTokens(this.#allDetectedTokens[chainId]);\n\n return [...new Set([...tokenAddresses, ...detectedTokenAddresses])].sort();\n }\n\n /**\n * Allows controller to make active and passive polling requests\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Blocks controller from making network calls\n */\n disable(): void {\n this.#disabled = true;\n }\n\n /**\n * Start (or restart) polling.\n *\n * @param chainId - The chain ID.\n * @param nativeCurrency - The native currency.\n */\n async start(chainId: Hex, nativeCurrency: string) {\n this.#stopPoll();\n this.#pollState = PollState.Active;\n await this.#poll(chainId, nativeCurrency);\n }\n\n /**\n * Stop polling.\n */\n stop() {\n this.#stopPoll();\n this.#pollState = PollState.Inactive;\n }\n\n #getTokensControllerState(): {\n allTokens: TokensControllerState['allTokens'];\n allDetectedTokens: TokensControllerState['allDetectedTokens'];\n } {\n const { allTokens, allDetectedTokens } = this.messagingSystem.call(\n 'TokensController:getState',\n );\n\n return {\n allTokens,\n allDetectedTokens,\n };\n }\n\n /**\n * Clear the active polling timer, if present.\n */\n #stopPoll() {\n if (this.#handle) {\n clearTimeout(this.#handle);\n }\n }\n\n /**\n * Poll for exchange rate updates.\n *\n * @param chainId - The chain ID.\n * @param nativeCurrency - The native currency.\n */\n async #poll(chainId: Hex, nativeCurrency: string) {\n await safelyExecute(() =>\n this.updateExchangeRates([{ chainId, nativeCurrency }]),\n );\n\n // Poll using recursive `setTimeout` instead of `setInterval` so that\n // requests don't stack if they take longer than the polling interval\n this.#handle = setTimeout(() => {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#poll(chainId, nativeCurrency);\n }, this.#interval);\n }\n\n /**\n * Updates exchange rates for all tokens.\n *\n * @param chainIdAndNativeCurrency - The chain ID and native currency.\n */\n async updateExchangeRates(\n chainIdAndNativeCurrency: {\n chainId: Hex;\n nativeCurrency: string;\n }[],\n ) {\n await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);\n }\n\n /**\n * Updates exchange rates for all tokens.\n *\n * @param chainIds - The chain IDs.\n * @returns A promise that resolves when all chain updates complete.\n */\n /**\n * Updates exchange rates for all tokens.\n *\n * @param chainIdAndNativeCurrency - The chain ID and native currency.\n */\n async updateExchangeRatesByChainId(\n chainIdAndNativeCurrency: {\n chainId: Hex;\n nativeCurrency: string;\n }[],\n ): Promise<void> {\n if (this.#disabled) {\n return;\n }\n\n // Create a promise for each chainId to fetch exchange rates.\n const updatePromises = chainIdAndNativeCurrency.map(\n async ({ chainId, nativeCurrency }) => {\n const tokenAddresses = this.#getTokenAddresses(chainId);\n // Build a unique key based on chainId, nativeCurrency, and the number of token addresses.\n const updateKey: `${Hex}:${string}` = `${chainId}:${nativeCurrency}:${tokenAddresses.length}`;\n\n if (updateKey in this.#inProcessExchangeRateUpdates) {\n // Await any ongoing update to avoid redundant work.\n await this.#inProcessExchangeRateUpdates[updateKey];\n return null;\n }\n\n // Create a deferred promise to track this update.\n const {\n promise: inProgressUpdate,\n resolve: updateSucceeded,\n reject: updateFailed,\n } = createDeferredPromise({ suppressUnhandledRejection: true });\n this.#inProcessExchangeRateUpdates[updateKey] = inProgressUpdate;\n\n try {\n const contractInformations = await this.#fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n\n // Each promise returns an object with the market data for the chain.\n const marketData = {\n [chainId]: {\n ...(contractInformations ?? {}),\n },\n };\n\n updateSucceeded();\n return marketData;\n } catch (error: unknown) {\n updateFailed(error);\n throw error;\n } finally {\n // Cleanup the tracking for this update.\n delete this.#inProcessExchangeRateUpdates[updateKey];\n }\n },\n );\n\n // Wait for all update promises to settle.\n const results = await Promise.allSettled(updatePromises);\n\n // Merge all successful market data updates into one object.\n const combinedMarketData = results.reduce((acc, result) => {\n if (result.status === 'fulfilled' && result.value) {\n acc = { ...acc, ...result.value };\n }\n return acc;\n }, {});\n\n // Call this.update only once with the combined market data to reduce the number of state changes and re-renders\n if (Object.keys(combinedMarketData).length > 0) {\n this.update((state) => {\n state.marketData = {\n ...state.marketData,\n ...combinedMarketData,\n };\n });\n }\n }\n\n /**\n * Uses the token prices service to retrieve exchange rates for tokens in a\n * particular currency.\n *\n * If the price API does not support the given chain ID, returns an empty\n * object.\n *\n * If the price API does not support the given currency, retrieves exchange\n * rates in a known currency instead, then converts those rates using the\n * exchange rate between the known currency and desired currency.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * exchange rates.\n * @returns A map from token address to its exchange rate in the native\n * currency, or an empty map if no exchange rates can be obtained for the\n * chain ID.\n */\n async #fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n if (!this.#tokenPricesService.validateChainIdSupported(chainId)) {\n return tokenAddresses.reduce((obj, tokenAddress) => {\n obj = {\n ...obj,\n [tokenAddress]: undefined,\n };\n\n return obj;\n }, {});\n }\n\n if (this.#tokenPricesService.validateCurrencySupported(nativeCurrency)) {\n return await this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n }\n\n return await this.#fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n chainId,\n tokenAddresses,\n nativeCurrency,\n });\n }\n\n /**\n * Updates token rates for the given networkClientId\n *\n * @param input - The input for the poll.\n * @param input.chainIdAndNativeCurrency - The chain ids and native currencies to poll token rates on.\n */\n async _executePoll({\n chainIdAndNativeCurrency,\n }: TokenRatesPollingInput): Promise<void> {\n await this.updateExchangeRatesByChainId(chainIdAndNativeCurrency);\n }\n\n /**\n * Retrieves prices in the given currency for the given tokens on the given\n * chain. Ensures that token addresses are checksum addresses.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n let contractNativeInformations;\n const tokenPricesByTokenAddress = await reduceInBatchesSerially<\n Hex,\n Awaited<ReturnType<AbstractTokenPricesService['fetchTokenPrices']>>\n >({\n values: [...tokenAddresses].sort(),\n batchSize: TOKEN_PRICES_BATCH_SIZE,\n eachBatch: async (allTokenPricesByTokenAddress, batch) => {\n const tokenPricesByTokenAddressForBatch =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: batch,\n chainId,\n currency: nativeCurrency,\n });\n\n return {\n ...allTokenPricesByTokenAddress,\n ...tokenPricesByTokenAddressForBatch,\n };\n },\n initialResult: {},\n });\n contractNativeInformations = tokenPricesByTokenAddress;\n\n // fetch for native token\n if (tokenAddresses.length === 0) {\n const contractNativeInformationsNative =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: [],\n chainId,\n currency: nativeCurrency,\n });\n\n contractNativeInformations = {\n [getNativeTokenAddress(chainId)]: {\n currency: nativeCurrency,\n ...contractNativeInformationsNative[getNativeTokenAddress(chainId)],\n },\n };\n }\n return Object.entries(contractNativeInformations).reduce(\n (obj, [tokenAddress, token]) => {\n obj = {\n ...obj,\n [tokenAddress]: { ...token },\n };\n\n return obj;\n },\n {},\n );\n }\n\n /**\n * If the price API does not support a given native currency, then we need to\n * convert it to a fallback currency and feed that currency into the price\n * API, then convert the prices to our desired native currency.\n *\n * @param args - The arguments to this function.\n * @param args.chainId - The chain id to fetch prices for.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n chainId,\n tokenAddresses,\n nativeCurrency,\n }: {\n chainId: Hex;\n tokenAddresses: Hex[];\n nativeCurrency: string;\n }): Promise<ContractMarketData> {\n const [\n contractExchangeInformations,\n fallbackCurrencyToNativeCurrencyConversionRate,\n ] = await Promise.all([\n this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency: FALL_BACK_VS_CURRENCY,\n }),\n getCurrencyConversionRate({\n from: FALL_BACK_VS_CURRENCY,\n to: nativeCurrency,\n }),\n ]);\n\n if (fallbackCurrencyToNativeCurrencyConversionRate === null) {\n return {};\n }\n\n // Converts the price in the fallback currency to the native currency\n const convertFallbackToNative = (value: number | undefined) =>\n value !== undefined && value !== null\n ? value * fallbackCurrencyToNativeCurrencyConversionRate\n : undefined;\n\n const updatedContractExchangeRates = Object.entries(\n contractExchangeInformations,\n ).reduce((acc, [tokenAddress, token]) => {\n acc = {\n ...acc,\n [tokenAddress]: {\n ...token,\n currency: nativeCurrency,\n price: convertFallbackToNative(token.price),\n marketCap: convertFallbackToNative(token.marketCap),\n allTimeHigh: convertFallbackToNative(token.allTimeHigh),\n allTimeLow: convertFallbackToNative(token.allTimeLow),\n totalVolume: convertFallbackToNative(token.totalVolume),\n high1d: convertFallbackToNative(token.high1d),\n low1d: convertFallbackToNative(token.low1d),\n dilutedMarketCap: convertFallbackToNative(token.dilutedMarketCap),\n },\n };\n return acc;\n }, {});\n\n return updatedContractExchangeRates;\n }\n\n /**\n * Reset the controller state to the default state.\n */\n resetState() {\n this.update(() => {\n return getDefaultTokenRatesControllerState();\n });\n }\n}\n\nexport default TokenRatesController;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/assets-controllers",
3
- "version": "58.0.0-preview-3d7a30d",
3
+ "version": "58.0.0-preview-d11c4815",
4
4
  "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
5
5
  "keywords": [
6
6
  "MetaMask",