@metamask-previews/assets-controllers 41.0.0-preview-db2c53b → 42.0.0-preview-651fe366

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.
@@ -1,21 +1,27 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
1
6
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
7
  if (kind === "m") throw new TypeError("Private method is not writable");
3
8
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
11
  };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _TokenBalancesController_handle, _TokenBalancesController_interval, _TokenBalancesController_tokens, _TokenBalancesController_disabled;
13
- import { BaseController } from "@metamask/base-controller";
14
- import { safelyExecute, toHex } from "@metamask/controller-utils";
12
+ var _TokenBalancesController_instances, _TokenBalancesController_queryMultipleAccounts, _TokenBalancesController_allTokens, _TokenBalancesController_allDetectedTokens, _TokenBalancesController_calculateQueryMultipleAccounts, _TokenBalancesController_onPreferencesStateChange, _TokenBalancesController_onTokensStateChange, _TokenBalancesController_getChainIds, _TokenBalancesController_getNetworkClient;
13
+ import { Contract } from "@ethersproject/contracts";
14
+ import { Web3Provider } from "@ethersproject/providers";
15
+ import { toChecksumHexAddress, toHex } from "@metamask/controller-utils";
16
+ import { abiERC20 } from "@metamask/metamask-eth-abis";
17
+ import { StaticIntervalPollingController } from "@metamask/polling-controller";
18
+ import $lodash from "lodash";
19
+ const { isEqual } = $lodash;
20
+ import { multicallOrFallback } from "./multicall.mjs";
15
21
  const DEFAULT_INTERVAL = 180000;
16
22
  const controllerName = 'TokenBalancesController';
17
23
  const metadata = {
18
- contractBalances: { persist: true, anonymous: false },
24
+ tokenBalances: { persist: true, anonymous: false },
19
25
  };
20
26
  /**
21
27
  * Get the default TokenBalancesController state.
@@ -24,25 +30,24 @@ const metadata = {
24
30
  */
25
31
  export function getDefaultTokenBalancesState() {
26
32
  return {
27
- contractBalances: {},
33
+ tokenBalances: {},
28
34
  };
29
35
  }
30
36
  /**
31
37
  * Controller that passively polls on a set interval token balances
32
38
  * for tokens stored in the TokensController
33
39
  */
34
- export class TokenBalancesController extends BaseController {
40
+ export class TokenBalancesController extends StaticIntervalPollingController() {
35
41
  /**
36
42
  * Construct a Token Balances Controller.
37
43
  *
38
44
  * @param options - The controller options.
39
45
  * @param options.interval - Polling interval used to fetch new token balances.
40
- * @param options.tokens - List of tokens to track balances for.
41
- * @param options.disabled - If set to true, all tracked tokens contract balances updates are blocked.
42
46
  * @param options.state - Initial state to set on this controller.
43
47
  * @param options.messenger - The controller restricted messenger.
44
48
  */
45
- constructor({ interval = DEFAULT_INTERVAL, tokens = [], disabled = false, messenger, state = {}, }) {
49
+ constructor({ interval = DEFAULT_INTERVAL, messenger, state = {}, }) {
50
+ var _a, _b;
46
51
  super({
47
52
  name: controllerName,
48
53
  metadata,
@@ -52,79 +57,97 @@ export class TokenBalancesController extends BaseController {
52
57
  ...state,
53
58
  },
54
59
  });
55
- _TokenBalancesController_handle.set(this, void 0);
56
- _TokenBalancesController_interval.set(this, void 0);
57
- _TokenBalancesController_tokens.set(this, void 0);
58
- _TokenBalancesController_disabled.set(this, void 0);
59
- __classPrivateFieldSet(this, _TokenBalancesController_disabled, disabled, "f");
60
- __classPrivateFieldSet(this, _TokenBalancesController_interval, interval, "f");
61
- __classPrivateFieldSet(this, _TokenBalancesController_tokens, tokens, "f");
62
- this.messagingSystem.subscribe('TokensController:stateChange', ({ tokens: newTokens, detectedTokens }) => {
63
- __classPrivateFieldSet(this, _TokenBalancesController_tokens, [...newTokens, ...detectedTokens], "f");
64
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
65
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
66
- this.updateBalances();
60
+ _TokenBalancesController_instances.add(this);
61
+ _TokenBalancesController_queryMultipleAccounts.set(this, void 0);
62
+ _TokenBalancesController_allTokens.set(this, void 0);
63
+ _TokenBalancesController_allDetectedTokens.set(this, void 0);
64
+ // Determines whether to query all accounts, or just the selected account
65
+ _TokenBalancesController_calculateQueryMultipleAccounts.set(this, ({ isMultiAccountBalancesEnabled, useMultiAccountBalanceChecker, }) => {
66
+ return Boolean(
67
+ // Note: These settings have different names on extension vs mobile
68
+ isMultiAccountBalancesEnabled || useMultiAccountBalanceChecker);
67
69
  });
68
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
69
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
70
- this.poll();
71
- }
72
- /**
73
- * Allows controller to update tracked tokens contract balances.
74
- */
75
- enable() {
76
- __classPrivateFieldSet(this, _TokenBalancesController_disabled, false, "f");
77
- }
78
- /**
79
- * Blocks controller from updating tracked tokens contract balances.
80
- */
81
- disable() {
82
- __classPrivateFieldSet(this, _TokenBalancesController_disabled, true, "f");
83
- }
84
- /**
85
- * Starts a new polling interval.
86
- *
87
- * @param interval - Polling interval used to fetch new token balances.
88
- */
89
- async poll(interval) {
90
- if (interval) {
91
- __classPrivateFieldSet(this, _TokenBalancesController_interval, interval, "f");
92
- }
93
- if (__classPrivateFieldGet(this, _TokenBalancesController_handle, "f")) {
94
- clearTimeout(__classPrivateFieldGet(this, _TokenBalancesController_handle, "f"));
95
- }
96
- await safelyExecute(() => this.updateBalances());
97
- __classPrivateFieldSet(this, _TokenBalancesController_handle, setTimeout(() => {
98
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
99
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
100
- this.poll(__classPrivateFieldGet(this, _TokenBalancesController_interval, "f"));
101
- }, __classPrivateFieldGet(this, _TokenBalancesController_interval, "f")), "f");
70
+ // Updates the user preference for whether to query multiple accounts
71
+ _TokenBalancesController_onPreferencesStateChange.set(this, async (preferences) => {
72
+ const queryMultipleAccounts = __classPrivateFieldGet(this, _TokenBalancesController_calculateQueryMultipleAccounts, "f").call(this, preferences);
73
+ // Refresh when flipped off -> on
74
+ const refresh = queryMultipleAccounts && !__classPrivateFieldGet(this, _TokenBalancesController_queryMultipleAccounts, "f");
75
+ __classPrivateFieldSet(this, _TokenBalancesController_queryMultipleAccounts, queryMultipleAccounts, "f");
76
+ if (refresh) {
77
+ await Promise.allSettled(__classPrivateFieldGet(this, _TokenBalancesController_getChainIds, "f").call(this, __classPrivateFieldGet(this, _TokenBalancesController_allTokens, "f"), __classPrivateFieldGet(this, _TokenBalancesController_allDetectedTokens, "f")).map(async (chainId) => this._executePoll({ chainId })));
78
+ }
79
+ });
80
+ // Refreshes token balances on chains whose tokens have changed
81
+ _TokenBalancesController_onTokensStateChange.set(this, async ({ allTokens, allDetectedTokens, }) => {
82
+ const chainIds = __classPrivateFieldGet(this, _TokenBalancesController_getChainIds, "f").call(this, allTokens, allDetectedTokens);
83
+ const chainIdsToUpdate = chainIds.filter((chainId) => !isEqual(__classPrivateFieldGet(this, _TokenBalancesController_allTokens, "f")[chainId], allTokens[chainId]) ||
84
+ !isEqual(__classPrivateFieldGet(this, _TokenBalancesController_allDetectedTokens, "f")[chainId], allDetectedTokens[chainId]));
85
+ __classPrivateFieldSet(this, _TokenBalancesController_allTokens, allTokens, "f");
86
+ __classPrivateFieldSet(this, _TokenBalancesController_allDetectedTokens, allDetectedTokens, "f");
87
+ await Promise.allSettled(chainIdsToUpdate.map(async (chainId) => this._executePoll({ chainId })));
88
+ });
89
+ // Returns an array of chain ids that have tokens
90
+ _TokenBalancesController_getChainIds.set(this, (allTokens, allDetectedTokens) => [
91
+ ...new Set([
92
+ ...Object.keys(allTokens),
93
+ ...Object.keys(allDetectedTokens),
94
+ ]),
95
+ ]);
96
+ this.setIntervalLength(interval);
97
+ // Set initial preference, and subscribe to changes
98
+ __classPrivateFieldSet(this, _TokenBalancesController_queryMultipleAccounts, __classPrivateFieldGet(this, _TokenBalancesController_calculateQueryMultipleAccounts, "f").call(this, this.messagingSystem.call('PreferencesController:getState')), "f");
99
+ this.messagingSystem.subscribe('PreferencesController:stateChange',
100
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
101
+ __classPrivateFieldGet(this, _TokenBalancesController_onPreferencesStateChange, "f").bind(this));
102
+ // Set initial tokens, and subscribe to changes
103
+ (_a = this, _b = this, {
104
+ allTokens: ({ set value(_c) { __classPrivateFieldSet(_a, _TokenBalancesController_allTokens, _c, "f"); } }).value,
105
+ allDetectedTokens: ({ set value(_c) { __classPrivateFieldSet(_b, _TokenBalancesController_allDetectedTokens, _c, "f"); } }).value,
106
+ } = this.messagingSystem.call('TokensController:getState'));
107
+ this.messagingSystem.subscribe('TokensController:stateChange',
108
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
109
+ __classPrivateFieldGet(this, _TokenBalancesController_onTokensStateChange, "f").bind(this));
102
110
  }
103
111
  /**
104
- * Updates balances for all tokens.
112
+ * Polls for erc20 token balances.
113
+ * @param input - The input for the poll.
114
+ * @param input.chainId - The chain id to poll token balances on.
105
115
  */
106
- async updateBalances() {
107
- if (__classPrivateFieldGet(this, _TokenBalancesController_disabled, "f")) {
116
+ async _executePoll({ chainId }) {
117
+ const { address: selectedAccountAddress } = this.messagingSystem.call('AccountsController:getSelectedAccount');
118
+ const isSelectedAccount = (accountAddress) => toChecksumHexAddress(accountAddress) ===
119
+ toChecksumHexAddress(selectedAccountAddress);
120
+ const accountTokenPairs = [];
121
+ const addTokens = ([accountAddress, tokens]) => __classPrivateFieldGet(this, _TokenBalancesController_queryMultipleAccounts, "f") || isSelectedAccount(accountAddress)
122
+ ? tokens.forEach((t) => accountTokenPairs.push({
123
+ accountAddress: accountAddress,
124
+ tokenAddress: t.address,
125
+ }))
126
+ : undefined;
127
+ Object.entries(__classPrivateFieldGet(this, _TokenBalancesController_allTokens, "f")[chainId] ?? {}).forEach(addTokens);
128
+ Object.entries(__classPrivateFieldGet(this, _TokenBalancesController_allDetectedTokens, "f")[chainId] ?? {}).forEach(addTokens);
129
+ if (accountTokenPairs.length === 0) {
108
130
  return;
109
131
  }
110
- const selectedInternalAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
111
- const newContractBalances = {};
112
- for (const token of __classPrivateFieldGet(this, _TokenBalancesController_tokens, "f")) {
113
- const { address } = token;
114
- try {
115
- const balance = await this.messagingSystem.call('AssetsContractController:getERC20BalanceOf', address, selectedInternalAccount.address);
116
- newContractBalances[address] = toHex(balance);
117
- token.hasBalanceError = false;
118
- }
119
- catch (error) {
120
- newContractBalances[address] = toHex(0);
121
- token.hasBalanceError = true;
122
- }
123
- }
132
+ const provider = new Web3Provider(__classPrivateFieldGet(this, _TokenBalancesController_instances, "m", _TokenBalancesController_getNetworkClient).call(this, chainId).provider);
133
+ const calls = accountTokenPairs.map(({ accountAddress, tokenAddress }) => ({
134
+ contract: new Contract(tokenAddress, abiERC20, provider),
135
+ functionSignature: 'balanceOf(address)',
136
+ arguments: [accountAddress],
137
+ }));
138
+ const results = await multicallOrFallback(calls, chainId, provider);
124
139
  this.update((state) => {
125
- state.contractBalances = newContractBalances;
140
+ var _a, _b;
141
+ for (let i = 0; i < results.length; i++) {
142
+ const { success, value } = results[i];
143
+ if (success) {
144
+ const { accountAddress, tokenAddress } = accountTokenPairs[i];
145
+ ((_b = ((_a = state.tokenBalances)[accountAddress] ?? (_a[accountAddress] = {})))[chainId] ?? (_b[chainId] = {}))[tokenAddress] = toHex(value);
146
+ }
147
+ }
126
148
  });
127
149
  }
150
+ // TODO: needed?
128
151
  /**
129
152
  * Reset the controller state to the default state.
130
153
  */
@@ -134,6 +157,14 @@ export class TokenBalancesController extends BaseController {
134
157
  });
135
158
  }
136
159
  }
137
- _TokenBalancesController_handle = new WeakMap(), _TokenBalancesController_interval = new WeakMap(), _TokenBalancesController_tokens = new WeakMap(), _TokenBalancesController_disabled = new WeakMap();
160
+ _TokenBalancesController_queryMultipleAccounts = new WeakMap(), _TokenBalancesController_allTokens = new WeakMap(), _TokenBalancesController_allDetectedTokens = new WeakMap(), _TokenBalancesController_calculateQueryMultipleAccounts = new WeakMap(), _TokenBalancesController_onPreferencesStateChange = new WeakMap(), _TokenBalancesController_onTokensStateChange = new WeakMap(), _TokenBalancesController_getChainIds = new WeakMap(), _TokenBalancesController_instances = new WeakSet(), _TokenBalancesController_getNetworkClient = function _TokenBalancesController_getNetworkClient(chainId) {
161
+ const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
162
+ const networkConfiguration = networkConfigurationsByChainId[chainId];
163
+ if (!networkConfiguration) {
164
+ throw new Error(`TokenBalancesController: No network configuration found for chainId ${chainId}`);
165
+ }
166
+ const { networkClientId } = networkConfiguration.rpcEndpoints[networkConfiguration.defaultRpcEndpointIndex];
167
+ return this.messagingSystem.call(`NetworkController:getNetworkClientById`, networkClientId);
168
+ };
138
169
  export default TokenBalancesController;
139
170
  //# sourceMappingURL=TokenBalancesController.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"TokenBalancesController.mjs","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountsControllerGetSelectedAccountAction } from '@metamask/accounts-controller';\nimport type {\n RestrictedControllerMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { safelyExecute, toHex } from '@metamask/controller-utils';\n\nimport type { AssetsContractControllerGetERC20BalanceOfAction } from './AssetsContractController';\nimport type { Token } from './TokenRatesController';\nimport type { TokensControllerStateChangeEvent } from './TokensController';\n\nconst DEFAULT_INTERVAL = 180000;\n\nconst controllerName = 'TokenBalancesController';\n\nconst metadata = {\n contractBalances: { persist: true, anonymous: false },\n};\n\n/**\n * Token balances controller options\n * @property interval - Polling interval used to fetch new token balances.\n * @property tokens - List of tokens to track balances for.\n * @property disabled - If set to true, all tracked tokens contract balances updates are blocked.\n */\ntype TokenBalancesControllerOptions = {\n interval?: number;\n tokens?: Token[];\n disabled?: boolean;\n messenger: TokenBalancesControllerMessenger;\n state?: Partial<TokenBalancesControllerState>;\n};\n\n/**\n * Represents a mapping of hash token contract addresses to their balances.\n */\ntype ContractBalances = Record<string, string>;\n\n/**\n * Token balances controller state\n * @property contractBalances - Hash of token contract addresses to balances\n */\nexport type TokenBalancesControllerState = {\n contractBalances: ContractBalances;\n};\n\nexport type TokenBalancesControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TokenBalancesControllerState\n>;\n\nexport type TokenBalancesControllerActions =\n TokenBalancesControllerGetStateAction;\n\nexport type AllowedActions =\n | AccountsControllerGetSelectedAccountAction\n | AssetsContractControllerGetERC20BalanceOfAction;\n\nexport type TokenBalancesControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n TokenBalancesControllerState\n >;\n\nexport type TokenBalancesControllerEvents =\n TokenBalancesControllerStateChangeEvent;\n\nexport type AllowedEvents = TokensControllerStateChangeEvent;\n\nexport type TokenBalancesControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n TokenBalancesControllerActions | AllowedActions,\n TokenBalancesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Get the default TokenBalancesController state.\n *\n * @returns The default TokenBalancesController state.\n */\nexport function getDefaultTokenBalancesState(): TokenBalancesControllerState {\n return {\n contractBalances: {},\n };\n}\n\n/**\n * Controller that passively polls on a set interval token balances\n * for tokens stored in the TokensController\n */\nexport class TokenBalancesController extends BaseController<\n typeof controllerName,\n TokenBalancesControllerState,\n TokenBalancesControllerMessenger\n> {\n #handle?: ReturnType<typeof setTimeout>;\n\n #interval: number;\n\n #tokens: Token[];\n\n #disabled: boolean;\n\n /**\n * Construct a Token Balances Controller.\n *\n * @param options - The controller options.\n * @param options.interval - Polling interval used to fetch new token balances.\n * @param options.tokens - List of tokens to track balances for.\n * @param options.disabled - If set to true, all tracked tokens contract balances updates are blocked.\n * @param options.state - Initial state to set on this controller.\n * @param options.messenger - The controller restricted messenger.\n */\n constructor({\n interval = DEFAULT_INTERVAL,\n tokens = [],\n disabled = false,\n messenger,\n state = {},\n }: TokenBalancesControllerOptions) {\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultTokenBalancesState(),\n ...state,\n },\n });\n\n this.#disabled = disabled;\n this.#interval = interval;\n this.#tokens = tokens;\n\n this.messagingSystem.subscribe(\n 'TokensController:stateChange',\n ({ tokens: newTokens, detectedTokens }) => {\n this.#tokens = [...newTokens, ...detectedTokens];\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.updateBalances();\n },\n );\n\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 }\n\n /**\n * Allows controller to update tracked tokens contract balances.\n */\n enable() {\n this.#disabled = false;\n }\n\n /**\n * Blocks controller from updating tracked tokens contract balances.\n */\n disable() {\n this.#disabled = true;\n }\n\n /**\n * Starts a new polling interval.\n *\n * @param interval - Polling interval used to fetch new token balances.\n */\n async poll(interval?: number): Promise<void> {\n if (interval) {\n this.#interval = interval;\n }\n\n if (this.#handle) {\n clearTimeout(this.#handle);\n }\n\n await safelyExecute(() => this.updateBalances());\n\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(this.#interval);\n }, this.#interval);\n }\n\n /**\n * Updates balances for all tokens.\n */\n async updateBalances() {\n if (this.#disabled) {\n return;\n }\n const selectedInternalAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n\n const newContractBalances: ContractBalances = {};\n for (const token of this.#tokens) {\n const { address } = token;\n try {\n const balance = await this.messagingSystem.call(\n 'AssetsContractController:getERC20BalanceOf',\n address,\n selectedInternalAccount.address,\n );\n newContractBalances[address] = toHex(balance);\n token.hasBalanceError = false;\n } catch (error) {\n newContractBalances[address] = toHex(0);\n token.hasBalanceError = true;\n }\n }\n\n this.update((state) => {\n state.contractBalances = newContractBalances;\n });\n }\n\n /**\n * Reset the controller state to the default state.\n */\n resetState() {\n this.update(() => {\n return getDefaultTokenBalancesState();\n });\n }\n}\n\nexport default TokenBalancesController;\n"]}
1
+ {"version":3,"file":"TokenBalancesController.mjs","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport type { AccountsControllerGetSelectedAccountAction } from '@metamask/accounts-controller';\nimport type {\n RestrictedControllerMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { toChecksumHexAddress, toHex } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type {\n PreferencesControllerGetStateAction,\n PreferencesControllerStateChangeEvent,\n PreferencesState,\n} from '@metamask/preferences-controller';\nimport type { Hex } from '@metamask/utils';\nimport type BN from 'bn.js';\nimport { isEqual } from 'lodash';\n\nimport { multicallOrFallback } from './multicall';\nimport type { Token } from './TokenRatesController';\nimport type {\n TokensControllerGetStateAction,\n TokensControllerState,\n TokensControllerStateChangeEvent,\n} from './TokensController';\n\nconst DEFAULT_INTERVAL = 180000;\n\nconst controllerName = 'TokenBalancesController';\n\nconst metadata = {\n tokenBalances: { persist: true, anonymous: false },\n};\n\n/**\n * Token balances controller options\n * @property interval - Polling interval used to fetch new token balances.\n * @property messenger - A controller messenger.\n * @property state - Initial state for the controller.\n */\ntype TokenBalancesControllerOptions = {\n interval?: number;\n messenger: TokenBalancesControllerMessenger;\n state?: Partial<TokenBalancesControllerState>;\n};\n\n/**\n * A mapping from account address to chain id to token address to balance.\n */\ntype TokenBalances = Record<Hex, Record<Hex, Record<Hex, Hex>>>;\n\n/**\n * Token balances controller state\n * @property tokenBalances - A mapping from account address to chain id to token address to balance.\n */\nexport type TokenBalancesControllerState = {\n tokenBalances: TokenBalances;\n};\n\nexport type TokenBalancesControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TokenBalancesControllerState\n>;\n\nexport type TokenBalancesControllerActions =\n TokenBalancesControllerGetStateAction;\n\nexport type AllowedActions =\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | TokensControllerGetStateAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction;\n\nexport type TokenBalancesControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n TokenBalancesControllerState\n >;\n\nexport type TokenBalancesControllerEvents =\n TokenBalancesControllerStateChangeEvent;\n\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | PreferencesControllerStateChangeEvent;\n\nexport type TokenBalancesControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n TokenBalancesControllerActions | AllowedActions,\n TokenBalancesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Get the default TokenBalancesController state.\n *\n * @returns The default TokenBalancesController state.\n */\nexport function getDefaultTokenBalancesState(): TokenBalancesControllerState {\n return {\n tokenBalances: {},\n };\n}\n\n/** The input to start polling for the {@link TokenBalancesController} */\nexport type TokenBalancesPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval token balances\n * for tokens stored in the TokensController\n */\nexport class TokenBalancesController extends StaticIntervalPollingController<TokenBalancesPollingInput>()<\n typeof controllerName,\n TokenBalancesControllerState,\n TokenBalancesControllerMessenger\n> {\n #queryMultipleAccounts: boolean;\n\n #allTokens: TokensControllerState['allTokens'];\n\n #allDetectedTokens: TokensControllerState['allDetectedTokens'];\n\n /**\n * Construct a Token Balances Controller.\n *\n * @param options - The controller options.\n * @param options.interval - Polling interval used to fetch new token balances.\n * @param options.state - Initial state to set on this controller.\n * @param options.messenger - The controller restricted messenger.\n */\n constructor({\n interval = DEFAULT_INTERVAL,\n messenger,\n state = {},\n }: TokenBalancesControllerOptions) {\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultTokenBalancesState(),\n ...state,\n },\n });\n\n this.setIntervalLength(interval);\n\n // Set initial preference, and subscribe to changes\n this.#queryMultipleAccounts = this.#calculateQueryMultipleAccounts(\n this.messagingSystem.call('PreferencesController:getState'),\n );\n this.messagingSystem.subscribe(\n 'PreferencesController:stateChange',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#onPreferencesStateChange.bind(this),\n );\n\n // Set initial tokens, and subscribe to changes\n ({\n allTokens: this.#allTokens,\n allDetectedTokens: this.#allDetectedTokens,\n } = this.messagingSystem.call('TokensController:getState'));\n\n this.messagingSystem.subscribe(\n 'TokensController:stateChange',\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#onTokensStateChange.bind(this),\n );\n }\n\n // Determines whether to query all accounts, or just the selected account\n #calculateQueryMultipleAccounts = ({\n isMultiAccountBalancesEnabled,\n useMultiAccountBalanceChecker,\n }: PreferencesState & { useMultiAccountBalanceChecker?: boolean }) => {\n return Boolean(\n // Note: These settings have different names on extension vs mobile\n isMultiAccountBalancesEnabled || useMultiAccountBalanceChecker,\n );\n };\n\n // Updates the user preference for whether to query multiple accounts\n #onPreferencesStateChange = async (preferences: PreferencesState) => {\n const queryMultipleAccounts =\n this.#calculateQueryMultipleAccounts(preferences);\n\n // Refresh when flipped off -> on\n const refresh = queryMultipleAccounts && !this.#queryMultipleAccounts;\n this.#queryMultipleAccounts = queryMultipleAccounts;\n\n if (refresh) {\n await Promise.allSettled(\n this.#getChainIds(this.#allTokens, this.#allDetectedTokens).map(\n async (chainId) => this._executePoll({ chainId }),\n ),\n );\n }\n };\n\n // Refreshes token balances on chains whose tokens have changed\n #onTokensStateChange = async ({\n allTokens,\n allDetectedTokens,\n }: TokensControllerState) => {\n const chainIds = this.#getChainIds(allTokens, allDetectedTokens);\n const chainIdsToUpdate = chainIds.filter(\n (chainId) =>\n !isEqual(this.#allTokens[chainId], allTokens[chainId]) ||\n !isEqual(this.#allDetectedTokens[chainId], allDetectedTokens[chainId]),\n );\n\n this.#allTokens = allTokens;\n this.#allDetectedTokens = allDetectedTokens;\n\n await Promise.allSettled(\n chainIdsToUpdate.map(async (chainId) => this._executePoll({ chainId })),\n );\n };\n\n // Returns an array of chain ids that have tokens\n #getChainIds = (\n allTokens: TokensControllerState['allTokens'],\n allDetectedTokens: TokensControllerState['allDetectedTokens'],\n ) =>\n [\n ...new Set([\n ...Object.keys(allTokens),\n ...Object.keys(allDetectedTokens),\n ]),\n ] as Hex[];\n\n /**\n * Polls for erc20 token balances.\n * @param input - The input for the poll.\n * @param input.chainId - The chain id to poll token balances on.\n */\n async _executePoll({ chainId }: TokenBalancesPollingInput): Promise<void> {\n const { address: selectedAccountAddress } = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n\n const isSelectedAccount = (accountAddress: string) =>\n toChecksumHexAddress(accountAddress) ===\n toChecksumHexAddress(selectedAccountAddress);\n\n const accountTokenPairs: { accountAddress: Hex; tokenAddress: Hex }[] = [];\n\n const addTokens = ([accountAddress, tokens]: [string, Token[]]) =>\n this.#queryMultipleAccounts || isSelectedAccount(accountAddress)\n ? tokens.forEach((t) =>\n accountTokenPairs.push({\n accountAddress: accountAddress as Hex,\n tokenAddress: t.address as Hex,\n }),\n )\n : undefined;\n\n Object.entries(this.#allTokens[chainId] ?? {}).forEach(addTokens);\n Object.entries(this.#allDetectedTokens[chainId] ?? {}).forEach(addTokens);\n\n if (accountTokenPairs.length === 0) {\n return;\n }\n\n const provider = new Web3Provider(this.#getNetworkClient(chainId).provider);\n\n const calls = accountTokenPairs.map(({ accountAddress, tokenAddress }) => ({\n contract: new Contract(tokenAddress, abiERC20, provider),\n functionSignature: 'balanceOf(address)',\n arguments: [accountAddress],\n }));\n\n const results = await multicallOrFallback(calls, chainId, provider);\n\n this.update((state) => {\n for (let i = 0; i < results.length; i++) {\n const { success, value } = results[i];\n\n if (success) {\n const { accountAddress, tokenAddress } = accountTokenPairs[i];\n ((state.tokenBalances[accountAddress] ??= {})[chainId] ??= {})[\n tokenAddress\n ] = toHex(value as BN);\n }\n }\n });\n }\n\n // TODO: needed?\n /**\n * Reset the controller state to the default state.\n */\n resetState() {\n this.update(() => {\n return getDefaultTokenBalancesState();\n });\n }\n\n // Returns the network client for a given chain id\n #getNetworkClient(chainId: Hex) {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n\n const networkConfiguration = networkConfigurationsByChainId[chainId];\n if (!networkConfiguration) {\n throw new Error(\n `TokenBalancesController: No network configuration found for chainId ${chainId}`,\n );\n }\n\n const { networkClientId } =\n networkConfiguration.rpcEndpoints[\n networkConfiguration.defaultRpcEndpointIndex\n ];\n\n return this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n networkClientId,\n );\n }\n}\n\nexport default TokenBalancesController;\n"]}
@@ -289,7 +289,7 @@ function divideIntoBatches(values, { batchSize }) {
289
289
  }
290
290
  exports.divideIntoBatches = divideIntoBatches;
291
291
  /**
292
- * Constructs an object from processing batches of the given values
292
+ * Constructs a result from processing batches of the given values
293
293
  * sequentially.
294
294
  *
295
295
  * @param args - The arguments to this function.
@@ -301,7 +301,7 @@ exports.divideIntoBatches = divideIntoBatches;
301
301
  * and the index, and should return an updated version of the object.
302
302
  * @param args.initialResult - The initial value of the final data structure,
303
303
  * i.e., the value that will be fed into the first call of `eachBatch`.
304
- * @returns The built object.
304
+ * @returns The built result.
305
305
  */
306
306
  async function reduceInBatchesSerially({ values, batchSize, eachBatch, initialResult, }) {
307
307
  const batches = divideIntoBatches(values, { batchSize });
@@ -1 +1 @@
1
- {"version":3,"file":"assetsUtil.cjs","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport {\n convertHexToDecimal,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { remove0x } from '@metamask/utils';\nimport BN from 'bn.js';\n\nimport type { Nft, NftMetadata } from './NftController';\nimport type { AbstractTokenPricesService } from './token-prices-service';\nimport { type ContractExchangeRates } from './TokenRatesController';\n\n/**\n * The maximum number of token addresses that should be sent to the Price API in\n * a single request.\n */\nexport const TOKEN_PRICES_BATCH_SIZE = 30;\n\n/**\n * Compares nft metadata entries to any nft entry.\n * We need this method when comparing a new fetched nft metadata, in case a entry changed to a defined value,\n * there's a need to update the nft in state.\n *\n * @param newNftMetadata - Nft metadata object.\n * @param nft - Nft object to compare with.\n * @returns Whether there are differences.\n */\nexport function compareNftMetadata(newNftMetadata: NftMetadata, nft: Nft) {\n const keys: (keyof NftMetadata)[] = [\n 'image',\n 'backgroundColor',\n 'imagePreview',\n 'imageThumbnail',\n 'imageOriginal',\n 'animation',\n 'animationOriginal',\n 'externalLink',\n 'tokenURI',\n ];\n const differentValues = keys.reduce((value, key) => {\n if (newNftMetadata[key] && newNftMetadata[key] !== nft[key]) {\n return value + 1;\n }\n return value;\n }, 0);\n return differentValues > 0;\n}\n\n/**\n * Checks whether the existing nft object has all the keys of the new incoming nft metadata object\n * @param newNftMetadata - New nft metadata object\n * @param nft - Existing nft object to compare with\n * @returns Whether the existing nft object has all the new keys from the new Nft metadata object\n */\nexport function hasNewCollectionFields(\n newNftMetadata: NftMetadata,\n nft: Nft,\n): boolean {\n const keysNewNftMetadata = Object.keys(newNftMetadata.collection ?? {});\n const keysExistingNft = new Set(Object.keys(nft.collection ?? {}));\n\n return keysNewNftMetadata.some((key) => !keysExistingNft.has(key));\n}\n\nconst aggregatorNameByKey: Record<string, string> = {\n aave: 'Aave',\n bancor: 'Bancor',\n cmc: 'CMC',\n cryptocom: 'Crypto.com',\n coinGecko: 'CoinGecko',\n oneInch: '1inch',\n paraswap: 'Paraswap',\n pmm: 'PMM',\n zapper: 'Zapper',\n zerion: 'Zerion',\n zeroEx: '0x',\n synthetix: 'Synthetix',\n yearn: 'Yearn',\n apeswap: 'ApeSwap',\n binanceDex: 'BinanceDex',\n pancakeTop100: 'PancakeTop100',\n pancakeExtended: 'PancakeExtended',\n balancer: 'Balancer',\n quickswap: 'QuickSwap',\n matcha: 'Matcha',\n pangolinDex: 'PangolinDex',\n pangolinDexStableCoin: 'PangolinDexStableCoin',\n pangolinDexAvaxBridge: 'PangolinDexAvaxBridge',\n traderJoe: 'TraderJoe',\n airswapLight: 'AirswapLight',\n kleros: 'Kleros',\n};\n\n/**\n * Formats aggregator names to presentable format.\n *\n * @param aggregators - List of token list names in camelcase.\n * @returns Formatted aggregator names.\n */\nexport const formatAggregatorNames = (aggregators: string[]) => {\n return aggregators.map(\n (key) =>\n aggregatorNameByKey[key] ||\n `${key[0].toUpperCase()}${key.substring(1, key.length)}`,\n );\n};\n\n/**\n * Format token list assets to use image proxy from Codefi.\n *\n * @param params - Object that contains chainID and tokenAddress.\n * @param params.chainId - ChainID of network in 0x-prefixed hexadecimal format.\n * @param params.tokenAddress - Address of token in mixed or lowercase.\n * @returns Formatted image url\n */\nexport const formatIconUrlWithProxy = ({\n chainId,\n tokenAddress,\n}: {\n chainId: Hex;\n tokenAddress: string;\n}) => {\n const chainIdDecimal = convertHexToDecimal(chainId).toString();\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `https://static.cx.metamask.io/api/v1/tokenIcons/${chainIdDecimal}/${tokenAddress.toLowerCase()}.png`;\n};\n\n/**\n * Networks where token detection is supported - Values are in hex format\n */\nexport enum SupportedTokenDetectionNetworks {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n mainnet = '0x1', // decimal: 1\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n bsc = '0x38', // decimal: 56\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n polygon = '0x89', // decimal: 137\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n avax = '0xa86a', // decimal: 43114\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n aurora = '0x4e454152', // decimal: 1313161554\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n linea_goerli = '0xe704', // decimal: 59140\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n linea_mainnet = '0xe708', // decimal: 59144\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n arbitrum = '0xa4b1', // decimal: 42161\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n optimism = '0xa', // decimal: 10\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n base = '0x2105', // decimal: 8453\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n zksync = '0x144', // decimal: 324\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n cronos = '0x19', // decimal: 25\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n celo = '0xa4ec', // decimal: 42220\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n gnosis = '0x64', // decimal: 100\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n fantom = '0xfa', // decimal: 250\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n polygon_zkevm = '0x44d', // decimal: 1101\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n moonbeam = '0x504', // decimal: 1284\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n moonriver = '0x505', // decimal: 1285\n}\n\n/**\n * Check if token detection is enabled for certain networks.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports token detection\n */\nexport function isTokenDetectionSupportedForNetwork(chainId: Hex): boolean {\n return Object.values<Hex>(SupportedTokenDetectionNetworks).includes(chainId);\n}\n\n/**\n * Check if token list polling is enabled for a given network.\n * Currently this method is used to support e2e testing for consumers of this package.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports tokenlists\n */\nexport function isTokenListSupportedForNetwork(chainId: Hex): boolean {\n return isTokenDetectionSupportedForNetwork(chainId);\n}\n\n/**\n * Removes IPFS protocol prefix from input string.\n *\n * @param ipfsUrl - An IPFS url (e.g. ipfs://{content id})\n * @returns IPFS content identifier and (possibly) path in a string\n * @throws Will throw if the url passed is not IPFS.\n */\nexport function removeIpfsProtocolPrefix(ipfsUrl: string) {\n if (ipfsUrl.startsWith('ipfs://ipfs/')) {\n return ipfsUrl.replace('ipfs://ipfs/', '');\n } else if (ipfsUrl.startsWith('ipfs://')) {\n return ipfsUrl.replace('ipfs://', '');\n }\n // this method should not be used with non-ipfs urls (i.e. startsWith('ipfs://') === true)\n throw new Error('this method should not be used with non ipfs urls');\n}\n\n/**\n * Extracts content identifier and path from an input string.\n *\n * @param ipfsUrl - An IPFS URL minus the IPFS protocol prefix\n * @returns IFPS content identifier (cid) and sub path as string.\n * @throws Will throw if the url passed is not ipfs.\n */\nexport async function getIpfsCIDv1AndPath(ipfsUrl: string): Promise<{\n cid: string;\n path?: string;\n}> {\n const url = removeIpfsProtocolPrefix(ipfsUrl);\n\n // check if there is a path\n // (CID is everything preceding first forward slash, path is everything after)\n const index = url.indexOf('/');\n const cid = index !== -1 ? url.substring(0, index) : url;\n const path = index !== -1 ? url.substring(index) : undefined;\n\n const { CID } = await import('multiformats');\n // We want to ensure that the CID is v1 (https://docs.ipfs.io/concepts/content-addressing/#identifier-formats)\n // because most cid v0s appear to be incompatible with IPFS subdomains\n return {\n cid: CID.parse(cid).toV1().toString(),\n path,\n };\n}\n\n/**\n * Formats URL correctly for use retrieving assets hosted on IPFS.\n *\n * @param ipfsGateway - The users preferred IPFS gateway (full URL or just host).\n * @param ipfsUrl - The IFPS URL pointed at the asset.\n * @param subdomainSupported - Boolean indicating whether the URL should be formatted with subdomains or not.\n * @returns A formatted URL, with the user's preferred IPFS gateway and format (subdomain or not), pointing to an asset hosted on IPFS.\n */\nexport async function getFormattedIpfsUrl(\n ipfsGateway: string,\n ipfsUrl: string,\n subdomainSupported: boolean,\n): Promise<string> {\n const { host, protocol, origin } = new URL(addUrlProtocolPrefix(ipfsGateway));\n if (subdomainSupported) {\n const { cid, path } = await getIpfsCIDv1AndPath(ipfsUrl);\n return `${protocol}//${cid}.ipfs.${host}${path ?? ''}`;\n }\n const cidAndPath = removeIpfsProtocolPrefix(ipfsUrl);\n return `${origin}/ipfs/${cidAndPath}`;\n}\n\n/**\n * Adds URL protocol prefix to input URL string if missing.\n *\n * @param urlString - An IPFS URL.\n * @returns A URL with a https:// prepended.\n */\nexport function addUrlProtocolPrefix(urlString: string): string {\n if (!urlString.match(/(^http:\\/\\/)|(^https:\\/\\/)/u)) {\n return `https://${urlString}`;\n }\n return urlString;\n}\n\n/**\n * Converts an Ethers BigNumber to a BN.\n *\n * @param bigNumber - An Ethers BigNumber instance.\n * @returns A BN object.\n */\nexport function ethersBigNumberToBN(bigNumber: BigNumber): BN {\n return new BN(remove0x(bigNumber.toHexString()), 'hex');\n}\n\n/**\n * Partitions a list of values into groups that are at most `batchSize` in\n * length.\n *\n * @param values - The list of values.\n * @param args - The remaining arguments.\n * @param args.batchSize - The desired maximum number of values per batch.\n * @returns The list of batches.\n */\nexport function divideIntoBatches<Value>(\n values: Value[],\n { batchSize }: { batchSize: number },\n): Value[][] {\n const batches = [];\n for (let i = 0; i < values.length; i += batchSize) {\n batches.push(values.slice(i, i + batchSize));\n }\n return batches;\n}\n\n/**\n * Constructs an object from processing batches of the given values\n * sequentially.\n *\n * @param args - The arguments to this function.\n * @param args.values - A list of values to iterate over.\n * @param args.batchSize - The maximum number of values in each batch.\n * @param args.eachBatch - A function to call for each batch. This function is\n * similar to the function that `Array.prototype.reduce` takes, in that it\n * receives the object that is being built, each batch in the list of batches\n * and the index, and should return an updated version of the object.\n * @param args.initialResult - The initial value of the final data structure,\n * i.e., the value that will be fed into the first call of `eachBatch`.\n * @returns The built object.\n */\nexport async function reduceInBatchesSerially<\n Value,\n Result extends Record<PropertyKey, unknown>,\n>({\n values,\n batchSize,\n eachBatch,\n initialResult,\n}: {\n values: Value[];\n batchSize: number;\n eachBatch: (\n workingResult: Partial<Result>,\n batch: Value[],\n index: number,\n ) => Partial<Result> | Promise<Partial<Result>>;\n initialResult: Partial<Result>;\n}): Promise<Result> {\n const batches = divideIntoBatches(values, { batchSize });\n let workingResult = initialResult;\n for (const [index, batch] of batches.entries()) {\n workingResult = await eachBatch(workingResult, batch, index);\n }\n // There's no way around this — we have to assume that in the end, the result\n // matches the intended type.\n const finalResult = workingResult as Result;\n return finalResult;\n}\n\n/**\n * Retrieves token prices for a set of contract addresses in a specific currency and chainId.\n *\n * @param args - The arguments to function.\n * @param args.tokenPricesService - An object in charge of retrieving token prices.\n * @param args.nativeCurrency - The native currency to request price in.\n * @param args.tokenAddresses - The list of contract addresses.\n * @param args.chainId - The chainId of the tokens.\n * @returns The prices for the requested tokens.\n */\nexport async function fetchTokenContractExchangeRates({\n tokenPricesService,\n nativeCurrency,\n tokenAddresses,\n chainId,\n}: {\n tokenPricesService: AbstractTokenPricesService;\n nativeCurrency: string;\n tokenAddresses: Hex[];\n chainId: Hex;\n}): Promise<ContractExchangeRates> {\n const isChainIdSupported =\n tokenPricesService.validateChainIdSupported(chainId);\n const isCurrencySupported =\n tokenPricesService.validateCurrencySupported(nativeCurrency);\n\n if (!isChainIdSupported || !isCurrencySupported) {\n return {};\n }\n\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 tokenPricesService.fetchTokenPrices({\n tokenAddresses: batch,\n chainId,\n currency: nativeCurrency,\n });\n\n return {\n ...allTokenPricesByTokenAddress,\n ...tokenPricesByTokenAddressForBatch,\n };\n },\n initialResult: {},\n });\n\n return Object.entries(tokenPricesByTokenAddress).reduce(\n (obj, [tokenAddress, tokenPrice]) => {\n return {\n ...obj,\n [toChecksumHexAddress(tokenAddress)]: tokenPrice?.price,\n };\n },\n {},\n );\n}\n"]}
1
+ {"version":3,"file":"assetsUtil.cjs","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport {\n convertHexToDecimal,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { remove0x } from '@metamask/utils';\nimport BN from 'bn.js';\n\nimport type { Nft, NftMetadata } from './NftController';\nimport type { AbstractTokenPricesService } from './token-prices-service';\nimport { type ContractExchangeRates } from './TokenRatesController';\n\n/**\n * The maximum number of token addresses that should be sent to the Price API in\n * a single request.\n */\nexport const TOKEN_PRICES_BATCH_SIZE = 30;\n\n/**\n * Compares nft metadata entries to any nft entry.\n * We need this method when comparing a new fetched nft metadata, in case a entry changed to a defined value,\n * there's a need to update the nft in state.\n *\n * @param newNftMetadata - Nft metadata object.\n * @param nft - Nft object to compare with.\n * @returns Whether there are differences.\n */\nexport function compareNftMetadata(newNftMetadata: NftMetadata, nft: Nft) {\n const keys: (keyof NftMetadata)[] = [\n 'image',\n 'backgroundColor',\n 'imagePreview',\n 'imageThumbnail',\n 'imageOriginal',\n 'animation',\n 'animationOriginal',\n 'externalLink',\n 'tokenURI',\n ];\n const differentValues = keys.reduce((value, key) => {\n if (newNftMetadata[key] && newNftMetadata[key] !== nft[key]) {\n return value + 1;\n }\n return value;\n }, 0);\n return differentValues > 0;\n}\n\n/**\n * Checks whether the existing nft object has all the keys of the new incoming nft metadata object\n * @param newNftMetadata - New nft metadata object\n * @param nft - Existing nft object to compare with\n * @returns Whether the existing nft object has all the new keys from the new Nft metadata object\n */\nexport function hasNewCollectionFields(\n newNftMetadata: NftMetadata,\n nft: Nft,\n): boolean {\n const keysNewNftMetadata = Object.keys(newNftMetadata.collection ?? {});\n const keysExistingNft = new Set(Object.keys(nft.collection ?? {}));\n\n return keysNewNftMetadata.some((key) => !keysExistingNft.has(key));\n}\n\nconst aggregatorNameByKey: Record<string, string> = {\n aave: 'Aave',\n bancor: 'Bancor',\n cmc: 'CMC',\n cryptocom: 'Crypto.com',\n coinGecko: 'CoinGecko',\n oneInch: '1inch',\n paraswap: 'Paraswap',\n pmm: 'PMM',\n zapper: 'Zapper',\n zerion: 'Zerion',\n zeroEx: '0x',\n synthetix: 'Synthetix',\n yearn: 'Yearn',\n apeswap: 'ApeSwap',\n binanceDex: 'BinanceDex',\n pancakeTop100: 'PancakeTop100',\n pancakeExtended: 'PancakeExtended',\n balancer: 'Balancer',\n quickswap: 'QuickSwap',\n matcha: 'Matcha',\n pangolinDex: 'PangolinDex',\n pangolinDexStableCoin: 'PangolinDexStableCoin',\n pangolinDexAvaxBridge: 'PangolinDexAvaxBridge',\n traderJoe: 'TraderJoe',\n airswapLight: 'AirswapLight',\n kleros: 'Kleros',\n};\n\n/**\n * Formats aggregator names to presentable format.\n *\n * @param aggregators - List of token list names in camelcase.\n * @returns Formatted aggregator names.\n */\nexport const formatAggregatorNames = (aggregators: string[]) => {\n return aggregators.map(\n (key) =>\n aggregatorNameByKey[key] ||\n `${key[0].toUpperCase()}${key.substring(1, key.length)}`,\n );\n};\n\n/**\n * Format token list assets to use image proxy from Codefi.\n *\n * @param params - Object that contains chainID and tokenAddress.\n * @param params.chainId - ChainID of network in 0x-prefixed hexadecimal format.\n * @param params.tokenAddress - Address of token in mixed or lowercase.\n * @returns Formatted image url\n */\nexport const formatIconUrlWithProxy = ({\n chainId,\n tokenAddress,\n}: {\n chainId: Hex;\n tokenAddress: string;\n}) => {\n const chainIdDecimal = convertHexToDecimal(chainId).toString();\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `https://static.cx.metamask.io/api/v1/tokenIcons/${chainIdDecimal}/${tokenAddress.toLowerCase()}.png`;\n};\n\n/**\n * Networks where token detection is supported - Values are in hex format\n */\nexport enum SupportedTokenDetectionNetworks {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n mainnet = '0x1', // decimal: 1\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n bsc = '0x38', // decimal: 56\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n polygon = '0x89', // decimal: 137\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n avax = '0xa86a', // decimal: 43114\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n aurora = '0x4e454152', // decimal: 1313161554\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n linea_goerli = '0xe704', // decimal: 59140\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n linea_mainnet = '0xe708', // decimal: 59144\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n arbitrum = '0xa4b1', // decimal: 42161\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n optimism = '0xa', // decimal: 10\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n base = '0x2105', // decimal: 8453\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n zksync = '0x144', // decimal: 324\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n cronos = '0x19', // decimal: 25\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n celo = '0xa4ec', // decimal: 42220\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n gnosis = '0x64', // decimal: 100\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n fantom = '0xfa', // decimal: 250\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n polygon_zkevm = '0x44d', // decimal: 1101\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n moonbeam = '0x504', // decimal: 1284\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n moonriver = '0x505', // decimal: 1285\n}\n\n/**\n * Check if token detection is enabled for certain networks.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports token detection\n */\nexport function isTokenDetectionSupportedForNetwork(chainId: Hex): boolean {\n return Object.values<Hex>(SupportedTokenDetectionNetworks).includes(chainId);\n}\n\n/**\n * Check if token list polling is enabled for a given network.\n * Currently this method is used to support e2e testing for consumers of this package.\n *\n * @param chainId - ChainID of network\n * @returns Whether the current network supports tokenlists\n */\nexport function isTokenListSupportedForNetwork(chainId: Hex): boolean {\n return isTokenDetectionSupportedForNetwork(chainId);\n}\n\n/**\n * Removes IPFS protocol prefix from input string.\n *\n * @param ipfsUrl - An IPFS url (e.g. ipfs://{content id})\n * @returns IPFS content identifier and (possibly) path in a string\n * @throws Will throw if the url passed is not IPFS.\n */\nexport function removeIpfsProtocolPrefix(ipfsUrl: string) {\n if (ipfsUrl.startsWith('ipfs://ipfs/')) {\n return ipfsUrl.replace('ipfs://ipfs/', '');\n } else if (ipfsUrl.startsWith('ipfs://')) {\n return ipfsUrl.replace('ipfs://', '');\n }\n // this method should not be used with non-ipfs urls (i.e. startsWith('ipfs://') === true)\n throw new Error('this method should not be used with non ipfs urls');\n}\n\n/**\n * Extracts content identifier and path from an input string.\n *\n * @param ipfsUrl - An IPFS URL minus the IPFS protocol prefix\n * @returns IFPS content identifier (cid) and sub path as string.\n * @throws Will throw if the url passed is not ipfs.\n */\nexport async function getIpfsCIDv1AndPath(ipfsUrl: string): Promise<{\n cid: string;\n path?: string;\n}> {\n const url = removeIpfsProtocolPrefix(ipfsUrl);\n\n // check if there is a path\n // (CID is everything preceding first forward slash, path is everything after)\n const index = url.indexOf('/');\n const cid = index !== -1 ? url.substring(0, index) : url;\n const path = index !== -1 ? url.substring(index) : undefined;\n\n const { CID } = await import('multiformats');\n // We want to ensure that the CID is v1 (https://docs.ipfs.io/concepts/content-addressing/#identifier-formats)\n // because most cid v0s appear to be incompatible with IPFS subdomains\n return {\n cid: CID.parse(cid).toV1().toString(),\n path,\n };\n}\n\n/**\n * Formats URL correctly for use retrieving assets hosted on IPFS.\n *\n * @param ipfsGateway - The users preferred IPFS gateway (full URL or just host).\n * @param ipfsUrl - The IFPS URL pointed at the asset.\n * @param subdomainSupported - Boolean indicating whether the URL should be formatted with subdomains or not.\n * @returns A formatted URL, with the user's preferred IPFS gateway and format (subdomain or not), pointing to an asset hosted on IPFS.\n */\nexport async function getFormattedIpfsUrl(\n ipfsGateway: string,\n ipfsUrl: string,\n subdomainSupported: boolean,\n): Promise<string> {\n const { host, protocol, origin } = new URL(addUrlProtocolPrefix(ipfsGateway));\n if (subdomainSupported) {\n const { cid, path } = await getIpfsCIDv1AndPath(ipfsUrl);\n return `${protocol}//${cid}.ipfs.${host}${path ?? ''}`;\n }\n const cidAndPath = removeIpfsProtocolPrefix(ipfsUrl);\n return `${origin}/ipfs/${cidAndPath}`;\n}\n\n/**\n * Adds URL protocol prefix to input URL string if missing.\n *\n * @param urlString - An IPFS URL.\n * @returns A URL with a https:// prepended.\n */\nexport function addUrlProtocolPrefix(urlString: string): string {\n if (!urlString.match(/(^http:\\/\\/)|(^https:\\/\\/)/u)) {\n return `https://${urlString}`;\n }\n return urlString;\n}\n\n/**\n * Converts an Ethers BigNumber to a BN.\n *\n * @param bigNumber - An Ethers BigNumber instance.\n * @returns A BN object.\n */\nexport function ethersBigNumberToBN(bigNumber: BigNumber): BN {\n return new BN(remove0x(bigNumber.toHexString()), 'hex');\n}\n\n/**\n * Partitions a list of values into groups that are at most `batchSize` in\n * length.\n *\n * @param values - The list of values.\n * @param args - The remaining arguments.\n * @param args.batchSize - The desired maximum number of values per batch.\n * @returns The list of batches.\n */\nexport function divideIntoBatches<Value>(\n values: Value[],\n { batchSize }: { batchSize: number },\n): Value[][] {\n const batches = [];\n for (let i = 0; i < values.length; i += batchSize) {\n batches.push(values.slice(i, i + batchSize));\n }\n return batches;\n}\n\n/**\n * Constructs a result from processing batches of the given values\n * sequentially.\n *\n * @param args - The arguments to this function.\n * @param args.values - A list of values to iterate over.\n * @param args.batchSize - The maximum number of values in each batch.\n * @param args.eachBatch - A function to call for each batch. This function is\n * similar to the function that `Array.prototype.reduce` takes, in that it\n * receives the object that is being built, each batch in the list of batches\n * and the index, and should return an updated version of the object.\n * @param args.initialResult - The initial value of the final data structure,\n * i.e., the value that will be fed into the first call of `eachBatch`.\n * @returns The built result.\n */\nexport async function reduceInBatchesSerially<Value, Result>({\n values,\n batchSize,\n eachBatch,\n initialResult,\n}: {\n values: Value[];\n batchSize: number;\n eachBatch: (\n workingResult: Partial<Result>,\n batch: Value[],\n index: number,\n ) => Partial<Result> | Promise<Partial<Result>>;\n initialResult: Partial<Result>;\n}): Promise<Result> {\n const batches = divideIntoBatches(values, { batchSize });\n let workingResult = initialResult;\n for (const [index, batch] of batches.entries()) {\n workingResult = await eachBatch(workingResult, batch, index);\n }\n // There's no way around this — we have to assume that in the end, the result\n // matches the intended type.\n const finalResult = workingResult as Result;\n return finalResult;\n}\n\n/**\n * Retrieves token prices for a set of contract addresses in a specific currency and chainId.\n *\n * @param args - The arguments to function.\n * @param args.tokenPricesService - An object in charge of retrieving token prices.\n * @param args.nativeCurrency - The native currency to request price in.\n * @param args.tokenAddresses - The list of contract addresses.\n * @param args.chainId - The chainId of the tokens.\n * @returns The prices for the requested tokens.\n */\nexport async function fetchTokenContractExchangeRates({\n tokenPricesService,\n nativeCurrency,\n tokenAddresses,\n chainId,\n}: {\n tokenPricesService: AbstractTokenPricesService;\n nativeCurrency: string;\n tokenAddresses: Hex[];\n chainId: Hex;\n}): Promise<ContractExchangeRates> {\n const isChainIdSupported =\n tokenPricesService.validateChainIdSupported(chainId);\n const isCurrencySupported =\n tokenPricesService.validateCurrencySupported(nativeCurrency);\n\n if (!isChainIdSupported || !isCurrencySupported) {\n return {};\n }\n\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 tokenPricesService.fetchTokenPrices({\n tokenAddresses: batch,\n chainId,\n currency: nativeCurrency,\n });\n\n return {\n ...allTokenPricesByTokenAddress,\n ...tokenPricesByTokenAddressForBatch,\n };\n },\n initialResult: {},\n });\n\n return Object.entries(tokenPricesByTokenAddress).reduce(\n (obj, [tokenAddress, tokenPrice]) => {\n return {\n ...obj,\n [toChecksumHexAddress(tokenAddress)]: tokenPrice?.price,\n };\n },\n {},\n );\n}\n"]}
@@ -138,7 +138,7 @@ export declare function divideIntoBatches<Value>(values: Value[], { batchSize }:
138
138
  batchSize: number;
139
139
  }): Value[][];
140
140
  /**
141
- * Constructs an object from processing batches of the given values
141
+ * Constructs a result from processing batches of the given values
142
142
  * sequentially.
143
143
  *
144
144
  * @param args - The arguments to this function.
@@ -150,9 +150,9 @@ export declare function divideIntoBatches<Value>(values: Value[], { batchSize }:
150
150
  * and the index, and should return an updated version of the object.
151
151
  * @param args.initialResult - The initial value of the final data structure,
152
152
  * i.e., the value that will be fed into the first call of `eachBatch`.
153
- * @returns The built object.
153
+ * @returns The built result.
154
154
  */
155
- export declare function reduceInBatchesSerially<Value, Result extends Record<PropertyKey, unknown>>({ values, batchSize, eachBatch, initialResult, }: {
155
+ export declare function reduceInBatchesSerially<Value, Result>({ values, batchSize, eachBatch, initialResult, }: {
156
156
  values: Value[];
157
157
  batchSize: number;
158
158
  eachBatch: (workingResult: Partial<Result>, batch: Value[], index: number) => Partial<Result> | Promise<Partial<Result>>;
@@ -1 +1 @@
1
- {"version":3,"file":"assetsUtil.d.cts","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"assetsUtil.d.cts","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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"}
@@ -138,7 +138,7 @@ export declare function divideIntoBatches<Value>(values: Value[], { batchSize }:
138
138
  batchSize: number;
139
139
  }): Value[][];
140
140
  /**
141
- * Constructs an object from processing batches of the given values
141
+ * Constructs a result from processing batches of the given values
142
142
  * sequentially.
143
143
  *
144
144
  * @param args - The arguments to this function.
@@ -150,9 +150,9 @@ export declare function divideIntoBatches<Value>(values: Value[], { batchSize }:
150
150
  * and the index, and should return an updated version of the object.
151
151
  * @param args.initialResult - The initial value of the final data structure,
152
152
  * i.e., the value that will be fed into the first call of `eachBatch`.
153
- * @returns The built object.
153
+ * @returns The built result.
154
154
  */
155
- export declare function reduceInBatchesSerially<Value, Result extends Record<PropertyKey, unknown>>({ values, batchSize, eachBatch, initialResult, }: {
155
+ export declare function reduceInBatchesSerially<Value, Result>({ values, batchSize, eachBatch, initialResult, }: {
156
156
  values: Value[];
157
157
  batchSize: number;
158
158
  eachBatch: (workingResult: Partial<Result>, batch: Value[], index: number) => Partial<Result> | Promise<Partial<Result>>;
@@ -1 +1 @@
1
- {"version":3,"file":"assetsUtil.d.mts","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"assetsUtil.d.mts","sourceRoot":"","sources":["../src/assetsUtil.ts"],"names":[],"mappings":"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"}
@@ -278,7 +278,7 @@ export function divideIntoBatches(values, { batchSize }) {
278
278
  return batches;
279
279
  }
280
280
  /**
281
- * Constructs an object from processing batches of the given values
281
+ * Constructs a result from processing batches of the given values
282
282
  * sequentially.
283
283
  *
284
284
  * @param args - The arguments to this function.
@@ -290,7 +290,7 @@ export function divideIntoBatches(values, { batchSize }) {
290
290
  * and the index, and should return an updated version of the object.
291
291
  * @param args.initialResult - The initial value of the final data structure,
292
292
  * i.e., the value that will be fed into the first call of `eachBatch`.
293
- * @returns The built object.
293
+ * @returns The built result.
294
294
  */
295
295
  export async function reduceInBatchesSerially({ values, batchSize, eachBatch, initialResult, }) {
296
296
  const batches = divideIntoBatches(values, { batchSize });