@metamask/assets-controllers 41.0.0 → 43.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/dist/AccountTrackerController.cjs +30 -10
  3. package/dist/AccountTrackerController.cjs.map +1 -1
  4. package/dist/AccountTrackerController.d.cts +14 -9
  5. package/dist/AccountTrackerController.d.cts.map +1 -1
  6. package/dist/AccountTrackerController.d.mts +14 -9
  7. package/dist/AccountTrackerController.d.mts.map +1 -1
  8. package/dist/AccountTrackerController.mjs +30 -10
  9. package/dist/AccountTrackerController.mjs.map +1 -1
  10. package/dist/AssetsContractController.cjs +61 -1
  11. package/dist/AssetsContractController.cjs.map +1 -1
  12. package/dist/AssetsContractController.d.cts +13 -0
  13. package/dist/AssetsContractController.d.cts.map +1 -1
  14. package/dist/AssetsContractController.d.mts +13 -0
  15. package/dist/AssetsContractController.d.mts.map +1 -1
  16. package/dist/AssetsContractController.mjs +61 -1
  17. package/dist/AssetsContractController.mjs.map +1 -1
  18. package/dist/CurrencyRateController.d.cts +4 -4
  19. package/dist/CurrencyRateController.d.mts +4 -4
  20. package/dist/NftController.cjs +8 -0
  21. package/dist/NftController.cjs.map +1 -1
  22. package/dist/NftController.d.cts +4 -0
  23. package/dist/NftController.d.cts.map +1 -1
  24. package/dist/NftController.d.mts +4 -0
  25. package/dist/NftController.d.mts.map +1 -1
  26. package/dist/NftController.mjs +8 -0
  27. package/dist/NftController.mjs.map +1 -1
  28. package/dist/TokenBalancesController.cjs +8 -0
  29. package/dist/TokenBalancesController.cjs.map +1 -1
  30. package/dist/TokenBalancesController.d.cts +4 -0
  31. package/dist/TokenBalancesController.d.cts.map +1 -1
  32. package/dist/TokenBalancesController.d.mts +4 -0
  33. package/dist/TokenBalancesController.d.mts.map +1 -1
  34. package/dist/TokenBalancesController.mjs +8 -0
  35. package/dist/TokenBalancesController.mjs.map +1 -1
  36. package/dist/TokenDetectionController.cjs +196 -129
  37. package/dist/TokenDetectionController.cjs.map +1 -1
  38. package/dist/TokenDetectionController.d.cts +23 -12
  39. package/dist/TokenDetectionController.d.cts.map +1 -1
  40. package/dist/TokenDetectionController.d.mts +23 -12
  41. package/dist/TokenDetectionController.d.mts.map +1 -1
  42. package/dist/TokenDetectionController.mjs +195 -129
  43. package/dist/TokenDetectionController.mjs.map +1 -1
  44. package/dist/TokenListController.cjs +60 -53
  45. package/dist/TokenListController.cjs.map +1 -1
  46. package/dist/TokenListController.d.cts +25 -14
  47. package/dist/TokenListController.d.cts.map +1 -1
  48. package/dist/TokenListController.d.mts +25 -14
  49. package/dist/TokenListController.d.mts.map +1 -1
  50. package/dist/TokenListController.mjs +60 -53
  51. package/dist/TokenListController.mjs.map +1 -1
  52. package/dist/TokenRatesController.cjs +43 -13
  53. package/dist/TokenRatesController.cjs.map +1 -1
  54. package/dist/TokenRatesController.d.cts +12 -8
  55. package/dist/TokenRatesController.d.cts.map +1 -1
  56. package/dist/TokenRatesController.d.mts +12 -8
  57. package/dist/TokenRatesController.d.mts.map +1 -1
  58. package/dist/TokenRatesController.mjs +43 -13
  59. package/dist/TokenRatesController.mjs.map +1 -1
  60. package/dist/TokensController.cjs +15 -4
  61. package/dist/TokensController.cjs.map +1 -1
  62. package/dist/TokensController.d.cts +4 -0
  63. package/dist/TokensController.d.cts.map +1 -1
  64. package/dist/TokensController.d.mts +4 -0
  65. package/dist/TokensController.d.mts.map +1 -1
  66. package/dist/TokensController.mjs +15 -4
  67. package/dist/TokensController.mjs.map +1 -1
  68. package/dist/assetsUtil.cjs +13 -1
  69. package/dist/assetsUtil.cjs.map +1 -1
  70. package/dist/assetsUtil.d.cts +7 -0
  71. package/dist/assetsUtil.d.cts.map +1 -1
  72. package/dist/assetsUtil.d.mts +7 -0
  73. package/dist/assetsUtil.d.mts.map +1 -1
  74. package/dist/assetsUtil.mjs +12 -0
  75. package/dist/assetsUtil.mjs.map +1 -1
  76. package/dist/multi-chain-accounts-service/mocks/mock-get-balances.cjs +18 -0
  77. package/dist/multi-chain-accounts-service/mocks/mock-get-balances.cjs.map +1 -1
  78. package/dist/multi-chain-accounts-service/mocks/mock-get-balances.d.cts.map +1 -1
  79. package/dist/multi-chain-accounts-service/mocks/mock-get-balances.d.mts.map +1 -1
  80. package/dist/multi-chain-accounts-service/mocks/mock-get-balances.mjs +18 -0
  81. package/dist/multi-chain-accounts-service/mocks/mock-get-balances.mjs.map +1 -1
  82. package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs +7 -2
  83. package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs.map +1 -1
  84. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts +3 -2
  85. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts.map +1 -1
  86. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts +3 -2
  87. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts.map +1 -1
  88. package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs +7 -2
  89. package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs.map +1 -1
  90. package/package.json +9 -9
@@ -1,5 +1,5 @@
1
1
  import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedControllerMessenger } from "@metamask/base-controller";
2
- import type { NetworkClientId, NetworkControllerStateChangeEvent, NetworkState, NetworkControllerGetNetworkClientByIdAction } from "@metamask/network-controller";
2
+ import type { NetworkControllerStateChangeEvent, NetworkState, NetworkControllerGetNetworkClientByIdAction } from "@metamask/network-controller";
3
3
  import type { Hex } from "@metamask/utils";
4
4
  declare const name = "TokenListController";
5
5
  export type TokenListToken = {
@@ -34,17 +34,17 @@ export type TokenListControllerMessenger = RestrictedControllerMessenger<typeof
34
34
  export declare const getDefaultTokenListState: () => TokenListState;
35
35
  /** The input to start polling for the {@link TokenListController} */
36
36
  type TokenListPollingInput = {
37
- networkClientId: NetworkClientId;
37
+ chainId: Hex;
38
38
  };
39
39
  declare const TokenListController_base: (abstract new (...args: any[]) => {
40
- readonly "__#787890@#intervalIds": Record<string, NodeJS.Timeout>;
41
- "__#787890@#intervalLength": number | undefined;
40
+ readonly "__#787887@#intervalIds": Record<string, NodeJS.Timeout>;
41
+ "__#787887@#intervalLength": number | undefined;
42
42
  setIntervalLength(intervalLength: number): void;
43
43
  getIntervalLength(): number | undefined;
44
44
  _startPolling(input: TokenListPollingInput): void;
45
45
  _stopPollingByPollingTokenSetId(key: string): void;
46
- readonly "__#787882@#pollingTokenSets": Map<string, Set<string>>;
47
- "__#787882@#callbacks": Map<string, Set<(input: TokenListPollingInput) => void>>;
46
+ readonly "__#787879@#pollingTokenSets": Map<string, Set<string>>;
47
+ "__#787879@#callbacks": Map<string, Set<(input: TokenListPollingInput) => void>>;
48
48
  _executePoll(input: TokenListPollingInput): Promise<void>;
49
49
  startPolling(input: TokenListPollingInput): string;
50
50
  stopAllPolling(): void;
@@ -85,38 +85,49 @@ export declare class TokenListController extends TokenListController_base<typeof
85
85
  });
86
86
  /**
87
87
  * Start polling for the token list.
88
+ * @deprecated This method is deprecated and will be removed in the future.
89
+ * Consider using the new polling approach instead
88
90
  */
89
91
  start(): Promise<void>;
90
92
  /**
91
93
  * Restart polling for the token list.
94
+ * @deprecated This method is deprecated and will be removed in the future.
95
+ * Consider using the new polling approach instead
92
96
  */
93
97
  restart(): Promise<void>;
94
98
  /**
95
99
  * Stop polling for the token list.
100
+ * @deprecated This method is deprecated and will be removed in the future.
101
+ * Consider using the new polling approach instead
96
102
  */
97
103
  stop(): void;
98
104
  /**
99
- * Prepare to discard this controller.
100
- *
101
105
  * This stops any active polling.
106
+ * @deprecated This method is deprecated and will be removed in the future.
107
+ * Consider using the new polling approach instead
102
108
  */
103
109
  destroy(): void;
110
+ /**
111
+ * This stops any active polling intervals.
112
+ * @deprecated This method is deprecated and will be removed in the future.
113
+ * Consider using the new polling approach instead
114
+ */
104
115
  private stopPolling;
105
116
  /**
106
- * Fetching token list from the Token Service API.
117
+ * This starts a new polling loop for any given chain. Under the hood it is deduping polls
107
118
  *
108
119
  * @private
109
120
  * @param input - The input for the poll.
110
- * @param input.networkClientId - The ID of the network client triggering the fetch.
121
+ * @param input.chainId - The chainId of the chain to trigger the fetch.
111
122
  * @returns A promise that resolves when this operation completes.
112
123
  */
113
- _executePoll({ networkClientId, }: TokenListPollingInput): Promise<void>;
124
+ _executePoll({ chainId }: TokenListPollingInput): Promise<void>;
114
125
  /**
115
- * Fetching token list from the Token Service API.
126
+ * Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)
116
127
  *
117
- * @param networkClientId - The ID of the network client triggering the fetch.
128
+ * @param chainId - The chainId of the current chain triggering the fetch.
118
129
  */
119
- fetchTokenList(networkClientId?: NetworkClientId): Promise<void>;
130
+ fetchTokenList(chainId: Hex): Promise<void>;
120
131
  /**
121
132
  * Clearing tokenList and tokensChainsCache explicitly.
122
133
  */
@@ -1 +1 @@
1
- {"version":3,"file":"TokenListController.d.mts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TokenListController.d.mts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
3
3
  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");
4
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
5
  };
6
- var _TokenListController_instances, _TokenListController_onNetworkControllerStateChange, _TokenListController_startPolling, _TokenListController_fetchFromCache;
6
+ var _TokenListController_instances, _TokenListController_onNetworkControllerStateChange, _TokenListController_startDeprecatedPolling, _TokenListController_fetchFromCache;
7
7
  import { safelyExecute } from "@metamask/controller-utils";
8
8
  import { StaticIntervalPollingController } from "@metamask/polling-controller";
9
9
  import { Mutex } from "async-mutex";
@@ -50,6 +50,7 @@ export class TokenListController extends StaticIntervalPollingController() {
50
50
  _TokenListController_instances.add(this);
51
51
  this.mutex = new Mutex();
52
52
  this.intervalDelay = interval;
53
+ this.setIntervalLength(interval);
53
54
  this.cacheRefreshThreshold = cacheRefreshThreshold;
54
55
  this.chainId = chainId;
55
56
  this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);
@@ -70,112 +71,116 @@ export class TokenListController extends StaticIntervalPollingController() {
70
71
  });
71
72
  }
72
73
  }
74
+ // Eventually we want to remove start/restart/stop controls in favor of new _executePoll API
75
+ // Maintaining these functions for now until we can safely deprecate them for backwards compatibility
73
76
  /**
74
77
  * Start polling for the token list.
78
+ * @deprecated This method is deprecated and will be removed in the future.
79
+ * Consider using the new polling approach instead
75
80
  */
76
81
  async start() {
77
82
  if (!isTokenListSupportedForNetwork(this.chainId)) {
78
83
  return;
79
84
  }
80
- await __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_startPolling).call(this);
85
+ await __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_startDeprecatedPolling).call(this);
81
86
  }
82
87
  /**
83
88
  * Restart polling for the token list.
89
+ * @deprecated This method is deprecated and will be removed in the future.
90
+ * Consider using the new polling approach instead
84
91
  */
85
92
  async restart() {
86
93
  this.stopPolling();
87
- await __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_startPolling).call(this);
94
+ await __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_startDeprecatedPolling).call(this);
88
95
  }
89
96
  /**
90
97
  * Stop polling for the token list.
98
+ * @deprecated This method is deprecated and will be removed in the future.
99
+ * Consider using the new polling approach instead
91
100
  */
92
101
  stop() {
93
102
  this.stopPolling();
94
103
  }
95
104
  /**
96
- * Prepare to discard this controller.
97
- *
98
105
  * This stops any active polling.
106
+ * @deprecated This method is deprecated and will be removed in the future.
107
+ * Consider using the new polling approach instead
99
108
  */
100
109
  destroy() {
101
110
  super.destroy();
102
111
  this.stopPolling();
103
112
  }
113
+ /**
114
+ * This stops any active polling intervals.
115
+ * @deprecated This method is deprecated and will be removed in the future.
116
+ * Consider using the new polling approach instead
117
+ */
104
118
  stopPolling() {
105
119
  if (this.intervalId) {
106
120
  clearInterval(this.intervalId);
107
121
  }
108
122
  }
109
123
  /**
110
- * Fetching token list from the Token Service API.
124
+ * This starts a new polling loop for any given chain. Under the hood it is deduping polls
111
125
  *
112
126
  * @private
113
127
  * @param input - The input for the poll.
114
- * @param input.networkClientId - The ID of the network client triggering the fetch.
128
+ * @param input.chainId - The chainId of the chain to trigger the fetch.
115
129
  * @returns A promise that resolves when this operation completes.
116
130
  */
117
- async _executePoll({ networkClientId, }) {
118
- return this.fetchTokenList(networkClientId);
131
+ async _executePoll({ chainId }) {
132
+ return this.fetchTokenList(chainId);
119
133
  }
120
134
  /**
121
- * Fetching token list from the Token Service API.
135
+ * Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)
122
136
  *
123
- * @param networkClientId - The ID of the network client triggering the fetch.
137
+ * @param chainId - The chainId of the current chain triggering the fetch.
124
138
  */
125
- async fetchTokenList(networkClientId) {
139
+ async fetchTokenList(chainId) {
126
140
  const releaseLock = await this.mutex.acquire();
127
- let networkClient;
128
- if (networkClientId) {
129
- networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientId);
130
- }
131
- const chainId = networkClient?.configuration.chainId ?? this.chainId;
132
141
  try {
133
142
  const { tokensChainsCache } = this.state;
134
143
  let tokenList = {};
144
+ // Attempt to fetch cached tokens
135
145
  const cachedTokens = await safelyExecute(() => __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_fetchFromCache).call(this, chainId));
136
146
  if (cachedTokens) {
137
147
  // Use non-expired cached tokens
138
148
  tokenList = { ...cachedTokens };
139
149
  }
140
150
  else {
141
- // Fetch fresh token list
151
+ // Fetch fresh token list from the API
142
152
  const tokensFromAPI = await safelyExecute(() => fetchTokenListByChainId(chainId, this.abortController.signal));
143
- if (!tokensFromAPI) {
144
- // Fallback to expired cached tokens
145
- tokenList = { ...(tokensChainsCache[chainId]?.data || {}) };
146
- this.update(() => {
147
- return {
148
- ...this.state,
149
- tokenList,
150
- tokensChainsCache,
153
+ if (tokensFromAPI) {
154
+ // Format tokens from API (HTTP) and update tokenList
155
+ tokenList = {};
156
+ for (const token of tokensFromAPI) {
157
+ tokenList[token.address] = {
158
+ ...token,
159
+ aggregators: formatAggregatorNames(token.aggregators),
160
+ iconUrl: formatIconUrlWithProxy({
161
+ chainId,
162
+ tokenAddress: token.address,
163
+ }),
151
164
  };
152
- });
153
- return;
165
+ }
154
166
  }
155
- for (const token of tokensFromAPI) {
156
- const formattedToken = {
157
- ...token,
158
- aggregators: formatAggregatorNames(token.aggregators),
159
- iconUrl: formatIconUrlWithProxy({
160
- chainId,
161
- tokenAddress: token.address,
162
- }),
163
- };
164
- tokenList[token.address] = formattedToken;
167
+ else {
168
+ // Fallback to expired cached tokens
169
+ tokenList = { ...(tokensChainsCache[chainId]?.data || {}) };
165
170
  }
166
171
  }
167
- const updatedTokensChainsCache = {
168
- ...tokensChainsCache,
169
- [chainId]: {
170
- timestamp: Date.now(),
171
- data: tokenList,
172
- },
173
- };
172
+ // Update the state with a single update for both tokenList and tokenChainsCache
174
173
  this.update(() => {
175
174
  return {
176
175
  ...this.state,
177
- tokenList,
178
- tokensChainsCache: updatedTokensChainsCache,
176
+ tokenList: this.chainId === chainId ? tokenList : this.state.tokenList,
177
+ tokensChainsCache: {
178
+ ...tokensChainsCache,
179
+ [chainId]: {
180
+ timestamp: Date.now(),
181
+ data: tokenList,
182
+ },
183
+ },
179
184
  };
180
185
  });
181
186
  }
@@ -234,19 +239,21 @@ async function _TokenListController_onNetworkControllerStateChange(networkContro
234
239
  tokenList: this.state.tokensChainsCache[this.chainId]?.data || {},
235
240
  };
236
241
  });
237
- await this.restart();
238
242
  }
239
243
  }
240
- }, _TokenListController_startPolling =
244
+ }, _TokenListController_startDeprecatedPolling =
241
245
  /**
242
- * Starts a new polling interval.
246
+ * Starts a new polling interval for a given chainId (this should be deprecated in favor of _executePoll)
247
+ * @deprecated This method is deprecated and will be removed in the future.
248
+ * Consider using the new polling approach instead
243
249
  */
244
- async function _TokenListController_startPolling() {
245
- await safelyExecute(() => this.fetchTokenList());
250
+ async function _TokenListController_startDeprecatedPolling() {
251
+ // renaming this to avoid collision with base class
252
+ await safelyExecute(() => this.fetchTokenList(this.chainId));
246
253
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
247
254
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
248
255
  this.intervalId = setInterval(async () => {
249
- await safelyExecute(() => this.fetchTokenList());
256
+ await safelyExecute(() => this.fetchTokenList(this.chainId));
250
257
  }, this.intervalDelay);
251
258
  }, _TokenListController_fetchFromCache =
252
259
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TokenListController.mjs","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenListByChainId } from './token-service';\n\nconst DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\nexport type TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokenList: TokenListMap;\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = ControllerStateChangeEvent<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerEvents = TokenListStateChange;\n\nexport type GetTokenListState = ControllerGetStateAction<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerActions = GetTokenListState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype AllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type TokenListControllerMessenger = RestrictedControllerMessenger<\n typeof name,\n TokenListControllerActions | AllowedActions,\n TokenListControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\nconst metadata = {\n tokenList: { persist: true, anonymous: true },\n tokensChainsCache: { persist: true, anonymous: true },\n preventPollingOnNetworkRestart: { persist: true, anonymous: true },\n};\n\nexport const getDefaultTokenListState = (): TokenListState => {\n return {\n tokenList: {},\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n };\n};\n\n/** The input to start polling for the {@link TokenListController} */\ntype TokenListPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends StaticIntervalPollingController<TokenListPollingInput>()<\n typeof name,\n TokenListState,\n TokenListControllerMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted controller messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListControllerMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...getDefaultTokenListState(), ...state },\n });\n this.intervalDelay = interval;\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\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 onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\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 (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(networkControllerState: NetworkState) {\n const selectedNetworkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkControllerState.selectedNetworkClientId,\n );\n const { chainId } = selectedNetworkClient.configuration;\n\n if (this.chainId !== chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n } else {\n // Ensure tokenList is referencing data from correct network\n this.update(() => {\n return {\n ...this.state,\n tokenList: this.state.tokensChainsCache[this.chainId]?.data || {},\n };\n });\n await this.restart();\n }\n }\n }\n\n /**\n * Start polling for the token list.\n */\n async start() {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.#startPolling();\n }\n\n /**\n * Restart polling for the token list.\n */\n async restart() {\n this.stopPolling();\n await this.#startPolling();\n }\n\n /**\n * Stop polling for the token list.\n */\n stop() {\n this.stopPolling();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval.\n */\n async #startPolling(): Promise<void> {\n await safelyExecute(() => this.fetchTokenList());\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 this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList());\n }, this.intervalDelay);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @private\n * @param input - The input for the poll.\n * @param input.networkClientId - The ID of the network client triggering the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll({\n networkClientId,\n }: TokenListPollingInput): Promise<void> {\n return this.fetchTokenList(networkClientId);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @param networkClientId - The ID of the network client triggering the fetch.\n */\n async fetchTokenList(networkClientId?: NetworkClientId): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n let networkClient;\n if (networkClientId) {\n networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n }\n const chainId = networkClient?.configuration.chainId ?? this.chainId;\n try {\n const { tokensChainsCache } = this.state;\n let tokenList: TokenListMap = {};\n const cachedTokens = await safelyExecute(() =>\n this.#fetchFromCache(chainId),\n );\n if (cachedTokens) {\n // Use non-expired cached tokens\n tokenList = { ...cachedTokens };\n } else {\n // Fetch fresh token list\n const tokensFromAPI = await safelyExecute(\n () =>\n fetchTokenListByChainId(\n chainId,\n this.abortController.signal,\n ) as Promise<TokenListToken[]>,\n );\n\n if (!tokensFromAPI) {\n // Fallback to expired cached tokens\n tokenList = { ...(tokensChainsCache[chainId]?.data || {}) };\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache,\n };\n });\n return;\n }\n for (const token of tokensFromAPI) {\n const formattedToken: TokenListToken = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n tokenList[token.address] = formattedToken;\n }\n }\n const updatedTokensChainsCache: TokensChainsCache = {\n ...tokensChainsCache,\n [chainId]: {\n timestamp: Date.now(),\n data: tokenList,\n },\n };\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache: updatedTokensChainsCache,\n };\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Checks if the Cache timestamp is valid,\n * if yes data in cache will be returned\n * otherwise null will be returned.\n * @param chainId - The chain ID of the network for which to fetch the cache.\n * @returns The cached data, or `null` if the cache was expired.\n */\n async #fetchFromCache(chainId: Hex): Promise<TokenListMap | null> {\n const { tokensChainsCache }: TokenListState = this.state;\n const dataCache = tokensChainsCache[chainId];\n const now = Date.now();\n if (\n dataCache?.data &&\n now - dataCache?.timestamp < this.cacheRefreshThreshold\n ) {\n return dataCache.data;\n }\n return null;\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokenList: {},\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
1
+ {"version":3,"file":"TokenListController.mjs","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type {\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenListByChainId } from './token-service';\n\nconst DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\nexport type TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokenList: TokenListMap;\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = ControllerStateChangeEvent<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerEvents = TokenListStateChange;\n\nexport type GetTokenListState = ControllerGetStateAction<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerActions = GetTokenListState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype AllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type TokenListControllerMessenger = RestrictedControllerMessenger<\n typeof name,\n TokenListControllerActions | AllowedActions,\n TokenListControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\nconst metadata = {\n tokenList: { persist: true, anonymous: true },\n tokensChainsCache: { persist: true, anonymous: true },\n preventPollingOnNetworkRestart: { persist: true, anonymous: true },\n};\n\nexport const getDefaultTokenListState = (): TokenListState => {\n return {\n tokenList: {},\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n };\n};\n\n/** The input to start polling for the {@link TokenListController} */\ntype TokenListPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends StaticIntervalPollingController<TokenListPollingInput>()<\n typeof name,\n TokenListState,\n TokenListControllerMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted controller messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListControllerMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...getDefaultTokenListState(), ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\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 onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\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 (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(networkControllerState: NetworkState) {\n const selectedNetworkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkControllerState.selectedNetworkClientId,\n );\n const { chainId } = selectedNetworkClient.configuration;\n\n if (this.chainId !== chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n } else {\n // Ensure tokenList is referencing data from correct network\n this.update(() => {\n return {\n ...this.state,\n tokenList: this.state.tokensChainsCache[this.chainId]?.data || {},\n };\n });\n }\n }\n }\n\n // Eventually we want to remove start/restart/stop controls in favor of new _executePoll API\n // Maintaining these functions for now until we can safely deprecate them for backwards compatibility\n /**\n * Start polling for the token list.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async start() {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Restart polling for the token list.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async restart() {\n this.stopPolling();\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Stop polling for the token list.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n stop() {\n this.stopPolling();\n }\n\n /**\n * This stops any active polling.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * This stops any active polling intervals.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval for a given chainId (this should be deprecated in favor of _executePoll)\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async #startDeprecatedPolling(): Promise<void> {\n // renaming this to avoid collision with base class\n await safelyExecute(() => this.fetchTokenList(this.chainId));\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 this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n }, this.intervalDelay);\n }\n\n /**\n * This starts a new polling loop for any given chain. Under the hood it is deduping polls\n *\n * @private\n * @param input - The input for the poll.\n * @param input.chainId - The chainId of the chain to trigger the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll({ chainId }: TokenListPollingInput): Promise<void> {\n return this.fetchTokenList(chainId);\n }\n\n /**\n * Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)\n *\n * @param chainId - The chainId of the current chain triggering the fetch.\n */\n async fetchTokenList(chainId: Hex): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n const { tokensChainsCache } = this.state;\n let tokenList: TokenListMap = {};\n // Attempt to fetch cached tokens\n const cachedTokens = await safelyExecute(() =>\n this.#fetchFromCache(chainId),\n );\n if (cachedTokens) {\n // Use non-expired cached tokens\n tokenList = { ...cachedTokens };\n } else {\n // Fetch fresh token list from the API\n const tokensFromAPI = await safelyExecute(\n () =>\n fetchTokenListByChainId(\n chainId,\n this.abortController.signal,\n ) as Promise<TokenListToken[]>,\n );\n\n if (tokensFromAPI) {\n // Format tokens from API (HTTP) and update tokenList\n tokenList = {};\n for (const token of tokensFromAPI) {\n tokenList[token.address] = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n }\n } else {\n // Fallback to expired cached tokens\n tokenList = { ...(tokensChainsCache[chainId]?.data || {}) };\n }\n }\n\n // Update the state with a single update for both tokenList and tokenChainsCache\n this.update(() => {\n return {\n ...this.state,\n tokenList:\n this.chainId === chainId ? tokenList : this.state.tokenList,\n tokensChainsCache: {\n ...tokensChainsCache,\n [chainId]: {\n timestamp: Date.now(),\n data: tokenList,\n },\n },\n };\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Checks if the Cache timestamp is valid,\n * if yes data in cache will be returned\n * otherwise null will be returned.\n * @param chainId - The chain ID of the network for which to fetch the cache.\n * @returns The cached data, or `null` if the cache was expired.\n */\n async #fetchFromCache(chainId: Hex): Promise<TokenListMap | null> {\n const { tokensChainsCache }: TokenListState = this.state;\n const dataCache = tokensChainsCache[chainId];\n const now = Date.now();\n if (\n dataCache?.data &&\n now - dataCache?.timestamp < this.cacheRefreshThreshold\n ) {\n return dataCache.data;\n }\n return null;\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokenList: {},\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
@@ -206,13 +206,26 @@ class TokenRatesController extends (0, polling_controller_1.StaticIntervalPollin
206
206
  * Updates token rates for the given networkClientId
207
207
  *
208
208
  * @param input - The input for the poll.
209
- * @param input.networkClientId - The network client ID used to get a ticker value.
209
+ * @param input.chainId - The chain id to poll token rates on.
210
210
  */
211
- async _executePoll({ networkClientId, }) {
212
- const networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientId);
211
+ async _executePoll({ chainId }) {
212
+ const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
213
+ const networkConfiguration = networkConfigurationsByChainId[chainId];
214
+ if (!networkConfiguration) {
215
+ console.error(`TokenRatesController: No network configuration found for chainId ${chainId}`);
216
+ return;
217
+ }
213
218
  await this.updateExchangeRatesByChainId({
214
- chainId: networkClient.configuration.chainId,
215
- nativeCurrency: networkClient.configuration.ticker,
219
+ chainId,
220
+ nativeCurrency: networkConfiguration.nativeCurrency,
221
+ });
222
+ }
223
+ /**
224
+ * Reset the controller state to the default state.
225
+ */
226
+ resetState() {
227
+ this.update(() => {
228
+ return (0, exports.getDefaultTokenRatesControllerState)();
216
229
  });
217
230
  }
218
231
  }
@@ -222,14 +235,29 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
222
235
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
223
236
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
224
237
  async ({ allTokens, allDetectedTokens }) => {
225
- const previousTokenAddresses = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getTokenAddresses).call(this, __classPrivateFieldGet(this, _TokenRatesController_chainId, "f"));
238
+ if (__classPrivateFieldGet(this, _TokenRatesController_disabled, "f")) {
239
+ return;
240
+ }
241
+ const chainIds = [
242
+ ...new Set([
243
+ ...Object.keys(allTokens),
244
+ ...Object.keys(allDetectedTokens),
245
+ ]),
246
+ ];
247
+ const chainIdsToUpdate = chainIds.filter((chainId) => !(0, lodash_1.isEqual)(__classPrivateFieldGet(this, _TokenRatesController_allTokens, "f")[chainId], allTokens[chainId]) ||
248
+ !(0, lodash_1.isEqual)(__classPrivateFieldGet(this, _TokenRatesController_allDetectedTokens, "f")[chainId], allDetectedTokens[chainId]));
226
249
  __classPrivateFieldSet(this, _TokenRatesController_allTokens, allTokens, "f");
227
250
  __classPrivateFieldSet(this, _TokenRatesController_allDetectedTokens, allDetectedTokens, "f");
228
- const newTokenAddresses = __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_getTokenAddresses).call(this, __classPrivateFieldGet(this, _TokenRatesController_chainId, "f"));
229
- if (!(0, lodash_1.isEqual)(previousTokenAddresses, newTokenAddresses) &&
230
- __classPrivateFieldGet(this, _TokenRatesController_pollState, "f") === PollState.Active) {
231
- await this.updateExchangeRates();
232
- }
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
+ }));
233
261
  }, ({ allTokens, allDetectedTokens }) => {
234
262
  return { allTokens, allDetectedTokens };
235
263
  });
@@ -324,6 +352,7 @@ async function _TokenRatesController_fetchAndMapExchangeRates({ tokenAddresses,
324
352
  });
325
353
  }
326
354
  return await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency).call(this, {
355
+ chainId,
327
356
  tokenAddresses,
328
357
  nativeCurrency,
329
358
  });
@@ -387,17 +416,18 @@ async function _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeC
387
416
  * API, then convert the prices to our desired native currency.
388
417
  *
389
418
  * @param args - The arguments to this function.
419
+ * @param args.chainId - The chain id to fetch prices for.
390
420
  * @param args.tokenAddresses - Addresses for tokens.
391
421
  * @param args.nativeCurrency - The native currency in which to request
392
422
  * prices.
393
423
  * @returns A map of the token addresses (as checksums) to their prices in the
394
424
  * native currency.
395
425
  */
396
- async function _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency({ tokenAddresses, nativeCurrency, }) {
426
+ async function _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency({ chainId, tokenAddresses, nativeCurrency, }) {
397
427
  const [contractExchangeInformations, fallbackCurrencyToNativeCurrencyConversionRate,] = await Promise.all([
398
428
  __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency).call(this, {
399
429
  tokenAddresses,
400
- chainId: __classPrivateFieldGet(this, _TokenRatesController_chainId, "f"),
430
+ chainId,
401
431
  nativeCurrency: controller_utils_1.FALL_BACK_VS_CURRENCY,
402
432
  }),
403
433
  getCurrencyConversionRate({