@metamask/assets-controllers 24.0.0 → 25.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [25.0.0]
10
+ ### Added
11
+ - Add Linea to price api supported chains ([#3797](https://github.com/MetaMask/core/pull/3797))
12
+
13
+ ### Changed
14
+ - **BREAKING:** Convert `TokenBalancesController` to `BaseControllerV2` ([#3750](https://github.com/MetaMask/core/pull/3750))
15
+ - The constructor parameters have changed; rather than accepting a "config" parameter for interval and tokens we now pass both values as controller options, and a "state" parameter, there is now just a single object for all constructor arguments. This object has a mandatory `messenger` and an optional `state`, `tokens`, `interval` properties a disabled property has also been added.
16
+ - State now saves tokens balances as strings and not as a BNs.
17
+ - Additional BN export has been removed as it was intended to be removed in the next major release.
18
+ - **BREAKING:** Bump `@metamask/approval-controller` peer dependency to `^5.1.2` ([#3821](https://github.com/MetaMask/core/pull/3821))
19
+ - **BREAKING:** Bump `@metamask/network-controller` peer dependency to `^17.2.0` ([#3821](https://github.com/MetaMask/core/pull/3821))
20
+ - **BREAKING:** Bump `@metamask/preferences-controller` peer dependency to `^7.0.0` ([#3821](https://github.com/MetaMask/core/pull/3821))
21
+ - Bump `@metamask/utils` to `^8.3.0` ([#3769](https://github.com/MetaMask/core/pull/3769))
22
+ - Bump `@metamask/base-controller` to `^4.1.1` ([#3760](https://github.com/MetaMask/core/pull/3760), [#3821](https://github.com/MetaMask/core/pull/3821))
23
+ - Bump `@metamask/controller-utils` to `^8.0.2` ([#3821](https://github.com/MetaMask/core/pull/3821))
24
+ - Bump `@metamask/polling-controller` to `^5.0.0` ([#3821](https://github.com/MetaMask/core/pull/3821))
25
+
9
26
  ## [24.0.0]
10
27
  ### Added
11
28
  - Add `getDefaultTokenListState` function to `TokenListController` ([#3744](https://github.com/MetaMask/core/pull/3744))
@@ -531,7 +548,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
531
548
  ### Changed
532
549
  - Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845))
533
550
 
534
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@24.0.0...HEAD
551
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@25.0.0...HEAD
552
+ [25.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@24.0.0...@metamask/assets-controllers@25.0.0
535
553
  [24.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@23.1.0...@metamask/assets-controllers@24.0.0
536
554
  [23.1.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@23.0.0...@metamask/assets-controllers@23.1.0
537
555
  [23.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@22.0.0...@metamask/assets-controllers@23.0.0
@@ -1,61 +1,72 @@
1
- /// <reference types="bn.js" />
2
- import type { BaseConfig, BaseState } from '@metamask/base-controller';
3
- import { BaseControllerV1 } from '@metamask/base-controller';
1
+ import { type RestrictedControllerMessenger, type ControllerGetStateAction, type ControllerStateChangeEvent, BaseController } from '@metamask/base-controller';
4
2
  import type { PreferencesState } from '@metamask/preferences-controller';
5
- import { BN } from 'ethereumjs-util';
6
3
  import type { AssetsContractController } from './AssetsContractController';
7
4
  import type { Token } from './TokenRatesController';
8
5
  import type { TokensState } from './TokensController';
9
- export { BN };
6
+ declare const controllerName = "TokenBalancesController";
10
7
  /**
11
- * @type TokenBalancesConfig
12
- *
13
- * Token balances controller configuration
14
- * @property interval - Polling interval used to fetch new token balances
15
- * @property tokens - List of tokens to track balances for
8
+ * Token balances controller options
9
+ * @property interval - Polling interval used to fetch new token balances.
10
+ * @property tokens - List of tokens to track balances for.
11
+ * @property disabled - If set to true, all tracked tokens contract balances updates are blocked.
12
+ * @property onTokensStateChange - Allows subscribing to assets controller state changes.
13
+ * @property getSelectedAddress - Gets the current selected address.
14
+ * @property getERC20BalanceOf - Gets the balance of the given account at the given contract address.
16
15
  */
17
- export interface TokenBalancesConfig extends BaseConfig {
18
- interval: number;
19
- tokens: Token[];
20
- }
16
+ declare type TokenBalancesControllerOptions = {
17
+ interval?: number;
18
+ tokens?: Token[];
19
+ disabled?: boolean;
20
+ onTokensStateChange: (listener: (tokenState: TokensState) => void) => void;
21
+ getSelectedAddress: () => PreferencesState['selectedAddress'];
22
+ getERC20BalanceOf: AssetsContractController['getERC20BalanceOf'];
23
+ messenger: TokenBalancesControllerMessenger;
24
+ state?: Partial<TokenBalancesControllerState>;
25
+ };
26
+ /**
27
+ * Represents a mapping of hash token contract addresses to their balances.
28
+ */
29
+ declare type ContractBalances = Record<string, string>;
21
30
  /**
22
- * @type TokenBalancesState
23
- *
24
31
  * Token balances controller state
25
32
  * @property contractBalances - Hash of token contract addresses to balances
26
33
  */
27
- export interface TokenBalancesState extends BaseState {
28
- contractBalances: {
29
- [address: string]: BN;
30
- };
31
- }
34
+ export declare type TokenBalancesControllerState = {
35
+ contractBalances: ContractBalances;
36
+ };
37
+ export declare type TokenBalancesControllerGetStateAction = ControllerGetStateAction<typeof controllerName, TokenBalancesControllerState>;
38
+ export declare type TokenBalancesControllerActions = TokenBalancesControllerGetStateAction;
39
+ export declare type TokenBalancesControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, TokenBalancesControllerState>;
40
+ export declare type TokenBalancesControllerEvents = TokenBalancesControllerStateChangeEvent;
41
+ export declare type TokenBalancesControllerMessenger = RestrictedControllerMessenger<typeof controllerName, TokenBalancesControllerActions, TokenBalancesControllerEvents, never, never>;
32
42
  /**
33
43
  * Controller that passively polls on a set interval token balances
34
44
  * for tokens stored in the TokensController
35
45
  */
36
- export declare class TokenBalancesController extends BaseControllerV1<TokenBalancesConfig, TokenBalancesState> {
37
- private handle?;
38
- /**
39
- * Name of this controller used during composition
40
- */
41
- name: string;
42
- private readonly getSelectedAddress;
43
- private readonly getERC20BalanceOf;
46
+ export declare class TokenBalancesController extends BaseController<typeof controllerName, TokenBalancesControllerState, TokenBalancesControllerMessenger> {
47
+ #private;
44
48
  /**
45
- * Creates a TokenBalancesController instance.
49
+ * Construct a Token Balances Controller.
46
50
  *
47
51
  * @param options - The controller options.
52
+ * @param options.interval - Polling interval used to fetch new token balances.
53
+ * @param options.tokens - List of tokens to track balances for.
54
+ * @param options.disabled - If set to true, all tracked tokens contract balances updates are blocked.
48
55
  * @param options.onTokensStateChange - Allows subscribing to assets controller state changes.
49
56
  * @param options.getSelectedAddress - Gets the current selected address.
50
57
  * @param options.getERC20BalanceOf - Gets the balance of the given account at the given contract address.
51
- * @param config - Initial options used to configure this controller.
52
- * @param state - Initial state to set on this controller.
58
+ * @param options.state - Initial state to set on this controller.
59
+ * @param options.messenger - The controller restricted messenger.
60
+ */
61
+ constructor({ interval, tokens, disabled, onTokensStateChange, getSelectedAddress, getERC20BalanceOf, messenger, state, }: TokenBalancesControllerOptions);
62
+ /**
63
+ * Allows controller to update tracked tokens contract balances.
64
+ */
65
+ enable(): void;
66
+ /**
67
+ * Blocks controller from updating tracked tokens contract balances.
53
68
  */
54
- constructor({ onTokensStateChange, getSelectedAddress, getERC20BalanceOf, }: {
55
- onTokensStateChange: (listener: (tokenState: TokensState) => void) => void;
56
- getSelectedAddress: () => PreferencesState['selectedAddress'];
57
- getERC20BalanceOf: AssetsContractController['getERC20BalanceOf'];
58
- }, config?: Partial<TokenBalancesConfig>, state?: Partial<TokenBalancesState>);
69
+ disable(): void;
59
70
  /**
60
71
  * Starts a new polling interval.
61
72
  *
@@ -1 +1 @@
1
- {"version":3,"file":"TokenBalancesController.d.ts","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAErC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,EAAE,EAAE,CAAC;AAEd;;;;;;GAMG;AAIH,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AAIH,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,gBAAgB,EAAE;QAAE,CAAC,OAAO,EAAE,MAAM,GAAG,EAAE,CAAA;KAAE,CAAC;CAC7C;AAED;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,gBAAgB,CAC3D,mBAAmB,EACnB,kBAAkB,CACnB;IACC,OAAO,CAAC,MAAM,CAAC,CAAgC;IAE/C;;OAEG;IACM,IAAI,SAA6B;IAE1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA4C;IAE/E,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgD;IAElF;;;;;;;;;OASG;gBAED,EACE,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAClB,EAAE;QACD,mBAAmB,EAAE,CACnB,QAAQ,EAAE,CAAC,UAAU,EAAE,WAAW,KAAK,IAAI,KACxC,IAAI,CAAC;QACV,kBAAkB,EAAE,MAAM,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;QAC9D,iBAAiB,EAAE,wBAAwB,CAAC,mBAAmB,CAAC,CAAC;KAClE,EACD,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,EACrC,KAAK,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC;IAkBrC;;;;OAIG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C;;OAEG;IACG,cAAc;CAqBrB;AAED,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"TokenBalancesController.d.ts","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,cAAc,EACf,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAMjD;;;;;;;;GAQG;AACH,aAAK,8BAA8B,GAAG;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mBAAmB,EAAE,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,WAAW,KAAK,IAAI,KAAK,IAAI,CAAC;IAC3E,kBAAkB,EAAE,MAAM,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;IAC9D,iBAAiB,EAAE,wBAAwB,CAAC,mBAAmB,CAAC,CAAC;IACjE,SAAS,EAAE,gCAAgC,CAAC;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;CAC/C,CAAC;AAEF;;GAEG;AACH,aAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/C;;;GAGG;AACH,oBAAY,4BAA4B,GAAG;IACzC,gBAAgB,EAAE,gBAAgB,CAAC;CACpC,CAAC;AAEF,oBAAY,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,oBAAY,8BAA8B,GACxC,qCAAqC,CAAC;AAExC,oBAAY,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ,oBAAY,6BAA6B,GACvC,uCAAuC,CAAC;AAE1C,oBAAY,gCAAgC,GAAG,6BAA6B,CAC1E,OAAO,cAAc,EACrB,8BAA8B,EAC9B,6BAA6B,EAC7B,KAAK,EACL,KAAK,CACN,CAAC;AAaF;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,cAAc,CACzD,OAAO,cAAc,EACrB,4BAA4B,EAC5B,gCAAgC,CACjC;;IAaC;;;;;;;;;;;;OAYG;gBACS,EACV,QAA2B,EAC3B,MAAW,EACX,QAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,SAAS,EACT,KAAU,GACX,EAAE,8BAA8B;IA+BjC;;OAEG;IACH,MAAM;IAIN;;OAEG;IACH,OAAO;IAIP;;;;OAIG;IACG,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB5C;;OAEG;IACG,cAAc;CAuBrB;AAED,eAAe,uBAAuB,CAAC"}
@@ -8,47 +8,89 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
12
+ if (kind === "m") throw new TypeError("Private method is not writable");
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
14
+ 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");
15
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
16
+ };
17
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
18
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
19
+ 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");
20
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
+ };
22
+ var _TokenBalancesController_instances, _TokenBalancesController_handle, _TokenBalancesController_getSelectedAddress, _TokenBalancesController_getERC20BalanceOf, _TokenBalancesController_interval, _TokenBalancesController_tokens, _TokenBalancesController_disabled, _TokenBalancesController_tokensStateChangeListener;
11
23
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.TokenBalancesController = exports.BN = void 0;
24
+ exports.TokenBalancesController = void 0;
13
25
  const base_controller_1 = require("@metamask/base-controller");
14
26
  const controller_utils_1 = require("@metamask/controller-utils");
15
- const ethereumjs_util_1 = require("ethereumjs-util");
16
- Object.defineProperty(exports, "BN", { enumerable: true, get: function () { return ethereumjs_util_1.BN; } });
27
+ const DEFAULT_INTERVAL = 180000;
28
+ const controllerName = 'TokenBalancesController';
29
+ const metadata = {
30
+ contractBalances: { persist: true, anonymous: false },
31
+ };
32
+ /**
33
+ * Get the default TokenBalancesController state.
34
+ *
35
+ * @returns The default TokenBalancesController state.
36
+ */
37
+ function getDefaultState() {
38
+ return {
39
+ contractBalances: {},
40
+ };
41
+ }
17
42
  /**
18
43
  * Controller that passively polls on a set interval token balances
19
44
  * for tokens stored in the TokensController
20
45
  */
21
- class TokenBalancesController extends base_controller_1.BaseControllerV1 {
46
+ class TokenBalancesController extends base_controller_1.BaseController {
22
47
  /**
23
- * Creates a TokenBalancesController instance.
48
+ * Construct a Token Balances Controller.
24
49
  *
25
50
  * @param options - The controller options.
51
+ * @param options.interval - Polling interval used to fetch new token balances.
52
+ * @param options.tokens - List of tokens to track balances for.
53
+ * @param options.disabled - If set to true, all tracked tokens contract balances updates are blocked.
26
54
  * @param options.onTokensStateChange - Allows subscribing to assets controller state changes.
27
55
  * @param options.getSelectedAddress - Gets the current selected address.
28
56
  * @param options.getERC20BalanceOf - Gets the balance of the given account at the given contract address.
29
- * @param config - Initial options used to configure this controller.
30
- * @param state - Initial state to set on this controller.
57
+ * @param options.state - Initial state to set on this controller.
58
+ * @param options.messenger - The controller restricted messenger.
31
59
  */
32
- constructor({ onTokensStateChange, getSelectedAddress, getERC20BalanceOf, }, config, state) {
33
- super(config, state);
34
- /**
35
- * Name of this controller used during composition
36
- */
37
- this.name = 'TokenBalancesController';
38
- this.defaultConfig = {
39
- interval: 180000,
40
- tokens: [],
41
- };
42
- this.defaultState = { contractBalances: {} };
43
- this.initialize();
44
- onTokensStateChange(({ tokens, detectedTokens }) => {
45
- this.configure({ tokens: [...tokens, ...detectedTokens] });
46
- this.updateBalances();
60
+ constructor({ interval = DEFAULT_INTERVAL, tokens = [], disabled = false, onTokensStateChange, getSelectedAddress, getERC20BalanceOf, messenger, state = {}, }) {
61
+ super({
62
+ name: controllerName,
63
+ metadata,
64
+ messenger,
65
+ state: Object.assign(Object.assign({}, getDefaultState()), state),
47
66
  });
48
- this.getSelectedAddress = getSelectedAddress;
49
- this.getERC20BalanceOf = getERC20BalanceOf;
67
+ _TokenBalancesController_instances.add(this);
68
+ _TokenBalancesController_handle.set(this, void 0);
69
+ _TokenBalancesController_getSelectedAddress.set(this, void 0);
70
+ _TokenBalancesController_getERC20BalanceOf.set(this, void 0);
71
+ _TokenBalancesController_interval.set(this, void 0);
72
+ _TokenBalancesController_tokens.set(this, void 0);
73
+ _TokenBalancesController_disabled.set(this, void 0);
74
+ __classPrivateFieldSet(this, _TokenBalancesController_disabled, disabled, "f");
75
+ __classPrivateFieldSet(this, _TokenBalancesController_interval, interval, "f");
76
+ __classPrivateFieldSet(this, _TokenBalancesController_tokens, tokens, "f");
77
+ onTokensStateChange(__classPrivateFieldGet(this, _TokenBalancesController_instances, "m", _TokenBalancesController_tokensStateChangeListener).bind(this));
78
+ __classPrivateFieldSet(this, _TokenBalancesController_getSelectedAddress, getSelectedAddress, "f");
79
+ __classPrivateFieldSet(this, _TokenBalancesController_getERC20BalanceOf, getERC20BalanceOf, "f");
50
80
  this.poll();
51
81
  }
82
+ /**
83
+ * Allows controller to update tracked tokens contract balances.
84
+ */
85
+ enable() {
86
+ __classPrivateFieldSet(this, _TokenBalancesController_disabled, false, "f");
87
+ }
88
+ /**
89
+ * Blocks controller from updating tracked tokens contract balances.
90
+ */
91
+ disable() {
92
+ __classPrivateFieldSet(this, _TokenBalancesController_disabled, true, "f");
93
+ }
52
94
  /**
53
95
  * Starts a new polling interval.
54
96
  *
@@ -56,12 +98,16 @@ class TokenBalancesController extends base_controller_1.BaseControllerV1 {
56
98
  */
57
99
  poll(interval) {
58
100
  return __awaiter(this, void 0, void 0, function* () {
59
- interval && this.configure({ interval }, false, false);
60
- this.handle && clearTimeout(this.handle);
101
+ if (interval) {
102
+ __classPrivateFieldSet(this, _TokenBalancesController_interval, interval, "f");
103
+ }
104
+ if (__classPrivateFieldGet(this, _TokenBalancesController_handle, "f")) {
105
+ clearTimeout(__classPrivateFieldGet(this, _TokenBalancesController_handle, "f"));
106
+ }
61
107
  yield (0, controller_utils_1.safelyExecute)(() => this.updateBalances());
62
- this.handle = setTimeout(() => {
63
- this.poll(this.config.interval);
64
- }, this.config.interval);
108
+ __classPrivateFieldSet(this, _TokenBalancesController_handle, setTimeout(() => {
109
+ this.poll(__classPrivateFieldGet(this, _TokenBalancesController_interval, "f"));
110
+ }, __classPrivateFieldGet(this, _TokenBalancesController_interval, "f")), "f");
65
111
  });
66
112
  }
67
113
  /**
@@ -69,26 +115,31 @@ class TokenBalancesController extends base_controller_1.BaseControllerV1 {
69
115
  */
70
116
  updateBalances() {
71
117
  return __awaiter(this, void 0, void 0, function* () {
72
- if (this.disabled) {
118
+ if (__classPrivateFieldGet(this, _TokenBalancesController_disabled, "f")) {
73
119
  return;
74
120
  }
75
- const { tokens } = this.config;
76
121
  const newContractBalances = {};
77
- for (const token of tokens) {
122
+ for (const token of __classPrivateFieldGet(this, _TokenBalancesController_tokens, "f")) {
78
123
  const { address } = token;
79
124
  try {
80
- newContractBalances[address] = yield this.getERC20BalanceOf(address, this.getSelectedAddress());
125
+ newContractBalances[address] = (0, controller_utils_1.toHex)(yield __classPrivateFieldGet(this, _TokenBalancesController_getERC20BalanceOf, "f").call(this, address, __classPrivateFieldGet(this, _TokenBalancesController_getSelectedAddress, "f").call(this)));
81
126
  token.balanceError = null;
82
127
  }
83
128
  catch (error) {
84
- newContractBalances[address] = new ethereumjs_util_1.BN(0);
129
+ newContractBalances[address] = (0, controller_utils_1.toHex)(0);
85
130
  token.balanceError = error;
86
131
  }
87
132
  }
88
- this.update({ contractBalances: newContractBalances });
133
+ this.update((state) => {
134
+ state.contractBalances = newContractBalances;
135
+ });
89
136
  });
90
137
  }
91
138
  }
92
139
  exports.TokenBalancesController = TokenBalancesController;
140
+ _TokenBalancesController_handle = new WeakMap(), _TokenBalancesController_getSelectedAddress = new WeakMap(), _TokenBalancesController_getERC20BalanceOf = new WeakMap(), _TokenBalancesController_interval = new WeakMap(), _TokenBalancesController_tokens = new WeakMap(), _TokenBalancesController_disabled = new WeakMap(), _TokenBalancesController_instances = new WeakSet(), _TokenBalancesController_tokensStateChangeListener = function _TokenBalancesController_tokensStateChangeListener({ tokens, detectedTokens }) {
141
+ __classPrivateFieldSet(this, _TokenBalancesController_tokens, [...tokens, ...detectedTokens], "f");
142
+ this.updateBalances();
143
+ };
93
144
  exports.default = TokenBalancesController;
94
145
  //# sourceMappingURL=TokenBalancesController.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TokenBalancesController.js","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,+DAA6D;AAC7D,iEAA2D;AAE3D,qDAAqC;AAO5B,mFAPA,oBAAE,OAOA;AA8BX;;;GAGG;AACH,MAAa,uBAAwB,SAAQ,kCAG5C;IAYC;;;;;;;;;OASG;IACH,YACE,EACE,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAOlB,EACD,MAAqC,EACrC,KAAmC;QAEnC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAlCvB;;WAEG;QACM,SAAI,GAAG,yBAAyB,CAAC;QAgCxC,IAAI,CAAC,aAAa,GAAG;YACnB,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,EAAE;SACX,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,EAAE;YACjD,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;YAC3D,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED;;;;OAIG;IACG,IAAI,CAAC,QAAiB;;YAC1B,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YACvD,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzC,MAAM,IAAA,gCAAa,EAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;YACjD,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAClC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;KAAA;IAED;;OAEG;IACG,cAAc;;YAClB,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,OAAO;aACR;YACD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;YAC/B,MAAM,mBAAmB,GAA8B,EAAE,CAAC;YAC1D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;gBAC1B,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;gBAC1B,IAAI;oBACF,mBAAmB,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,iBAAiB,CACzD,OAAO,EACP,IAAI,CAAC,kBAAkB,EAAE,CAC1B,CAAC;oBACF,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;iBAC3B;gBAAC,OAAO,KAAK,EAAE;oBACd,mBAAmB,CAAC,OAAO,CAAC,GAAG,IAAI,oBAAE,CAAC,CAAC,CAAC,CAAC;oBACzC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;iBAC5B;aACF;YACD,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACzD,CAAC;KAAA;CACF;AA9FD,0DA8FC;AAED,kBAAe,uBAAuB,CAAC","sourcesContent":["import type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport { BaseControllerV1 } from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport { BN } from 'ethereumjs-util';\n\nimport type { AssetsContractController } from './AssetsContractController';\nimport type { Token } from './TokenRatesController';\nimport type { TokensState } from './TokensController';\n\n// TODO: Remove this export in the next major release\nexport { BN };\n\n/**\n * @type TokenBalancesConfig\n *\n * Token balances controller configuration\n * @property interval - Polling interval used to fetch new token balances\n * @property tokens - List of tokens to track balances for\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface TokenBalancesConfig extends BaseConfig {\n interval: number;\n tokens: Token[];\n}\n\n/**\n * @type TokenBalancesState\n *\n * Token balances controller state\n * @property contractBalances - Hash of token contract addresses to balances\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface TokenBalancesState extends BaseState {\n contractBalances: { [address: string]: BN };\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 BaseControllerV1<\n TokenBalancesConfig,\n TokenBalancesState\n> {\n private handle?: ReturnType<typeof setTimeout>;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'TokenBalancesController';\n\n private readonly getSelectedAddress: () => PreferencesState['selectedAddress'];\n\n private readonly getERC20BalanceOf: AssetsContractController['getERC20BalanceOf'];\n\n /**\n * Creates a TokenBalancesController instance.\n *\n * @param options - The controller options.\n * @param options.onTokensStateChange - Allows subscribing to assets controller state changes.\n * @param options.getSelectedAddress - Gets the current selected address.\n * @param options.getERC20BalanceOf - Gets the balance of the given account at the given contract address.\n * @param config - Initial options used to configure this controller.\n * @param state - Initial state to set on this controller.\n */\n constructor(\n {\n onTokensStateChange,\n getSelectedAddress,\n getERC20BalanceOf,\n }: {\n onTokensStateChange: (\n listener: (tokenState: TokensState) => void,\n ) => void;\n getSelectedAddress: () => PreferencesState['selectedAddress'];\n getERC20BalanceOf: AssetsContractController['getERC20BalanceOf'];\n },\n config?: Partial<TokenBalancesConfig>,\n state?: Partial<TokenBalancesState>,\n ) {\n super(config, state);\n this.defaultConfig = {\n interval: 180000,\n tokens: [],\n };\n this.defaultState = { contractBalances: {} };\n this.initialize();\n onTokensStateChange(({ tokens, detectedTokens }) => {\n this.configure({ tokens: [...tokens, ...detectedTokens] });\n this.updateBalances();\n });\n this.getSelectedAddress = getSelectedAddress;\n this.getERC20BalanceOf = getERC20BalanceOf;\n this.poll();\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 interval && this.configure({ interval }, false, false);\n this.handle && clearTimeout(this.handle);\n await safelyExecute(() => this.updateBalances());\n this.handle = setTimeout(() => {\n this.poll(this.config.interval);\n }, this.config.interval);\n }\n\n /**\n * Updates balances for all tokens.\n */\n async updateBalances() {\n if (this.disabled) {\n return;\n }\n const { tokens } = this.config;\n const newContractBalances: { [address: string]: BN } = {};\n for (const token of tokens) {\n const { address } = token;\n try {\n newContractBalances[address] = await this.getERC20BalanceOf(\n address,\n this.getSelectedAddress(),\n );\n token.balanceError = null;\n } catch (error) {\n newContractBalances[address] = new BN(0);\n token.balanceError = error;\n }\n }\n this.update({ contractBalances: newContractBalances });\n }\n}\n\nexport default TokenBalancesController;\n"]}
1
+ {"version":3,"file":"TokenBalancesController.js","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type RestrictedControllerMessenger,\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n BaseController,\n} from '@metamask/base-controller';\nimport { safelyExecute, toHex } from '@metamask/controller-utils';\nimport type { PreferencesState } from '@metamask/preferences-controller';\n\nimport type { AssetsContractController } from './AssetsContractController';\nimport type { Token } from './TokenRatesController';\nimport type { TokensState } 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 * @property onTokensStateChange - Allows subscribing to assets controller state changes.\n * @property getSelectedAddress - Gets the current selected address.\n * @property getERC20BalanceOf - Gets the balance of the given account at the given contract address.\n */\ntype TokenBalancesControllerOptions = {\n interval?: number;\n tokens?: Token[];\n disabled?: boolean;\n onTokensStateChange: (listener: (tokenState: TokensState) => void) => void;\n getSelectedAddress: () => PreferencesState['selectedAddress'];\n getERC20BalanceOf: AssetsContractController['getERC20BalanceOf'];\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 TokenBalancesControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n TokenBalancesControllerState\n >;\n\nexport type TokenBalancesControllerEvents =\n TokenBalancesControllerStateChangeEvent;\n\nexport type TokenBalancesControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n TokenBalancesControllerActions,\n TokenBalancesControllerEvents,\n never,\n never\n>;\n\n/**\n * Get the default TokenBalancesController state.\n *\n * @returns The default TokenBalancesController state.\n */\nfunction getDefaultState(): 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 #getSelectedAddress: () => PreferencesState['selectedAddress'];\n\n #getERC20BalanceOf: AssetsContractController['getERC20BalanceOf'];\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.onTokensStateChange - Allows subscribing to assets controller state changes.\n * @param options.getSelectedAddress - Gets the current selected address.\n * @param options.getERC20BalanceOf - Gets the balance of the given account at the given contract address.\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 onTokensStateChange,\n getSelectedAddress,\n getERC20BalanceOf,\n messenger,\n state = {},\n }: TokenBalancesControllerOptions) {\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultState(),\n ...state,\n },\n });\n\n this.#disabled = disabled;\n this.#interval = interval;\n this.#tokens = tokens;\n\n onTokensStateChange(this.#tokensStateChangeListener.bind(this));\n\n this.#getSelectedAddress = getSelectedAddress;\n this.#getERC20BalanceOf = getERC20BalanceOf;\n\n this.poll();\n }\n\n /*\n * Tokens state changes listener.\n */\n #tokensStateChangeListener({ tokens, detectedTokens }: TokensState) {\n this.#tokens = [...tokens, ...detectedTokens];\n this.updateBalances();\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 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\n const newContractBalances: ContractBalances = {};\n for (const token of this.#tokens) {\n const { address } = token;\n try {\n newContractBalances[address] = toHex(\n await this.#getERC20BalanceOf(address, this.#getSelectedAddress()),\n );\n token.balanceError = null;\n } catch (error) {\n newContractBalances[address] = toHex(0);\n token.balanceError = error;\n }\n }\n\n this.update((state) => {\n state.contractBalances = newContractBalances;\n });\n }\n}\n\nexport default TokenBalancesController;\n"]}
@@ -2,7 +2,7 @@ import type { BaseConfig, BaseState } from '@metamask/base-controller';
2
2
  import type { NetworkClientId, NetworkController, NetworkState } from '@metamask/network-controller';
3
3
  import { StaticIntervalPollingControllerV1 } from '@metamask/polling-controller';
4
4
  import type { PreferencesState } from '@metamask/preferences-controller';
5
- import type { Hex } from '@metamask/utils';
5
+ import { type Hex } from '@metamask/utils';
6
6
  import type { AbstractTokenPricesService } from './token-prices-service/abstract-token-prices-service';
7
7
  import type { TokensState } from './TokensController';
8
8
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TokenRatesController.d.ts","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TokenRatesController.d.ts","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.TokenRatesController = void 0;
25
25
  const controller_utils_1 = require("@metamask/controller-utils");
26
26
  const polling_controller_1 = require("@metamask/polling-controller");
27
+ const utils_1 = require("@metamask/utils");
27
28
  const lodash_1 = require("lodash");
28
29
  const assetsUtil_1 = require("./assetsUtil");
29
30
  const crypto_compare_1 = require("./crypto-compare");
@@ -195,7 +196,7 @@ class TokenRatesController extends polling_controller_1.StaticIntervalPollingCon
195
196
  yield __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey];
196
197
  return;
197
198
  }
198
- const { promise: inProgressUpdate, resolve: updateSucceeded, reject: updateFailed, } = createDeferredPromise({ suppressUnhandledRejection: true });
199
+ const { promise: inProgressUpdate, resolve: updateSucceeded, reject: updateFailed, } = (0, utils_1.createDeferredPromise)({ suppressUnhandledRejection: true });
199
200
  __classPrivateFieldGet(this, _TokenRatesController_inProcessExchangeRateUpdates, "f")[updateKey] = inProgressUpdate;
200
201
  try {
201
202
  const newContractExchangeRates = yield __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRates).call(this, {
@@ -324,31 +325,5 @@ _TokenRatesController_pollState = new WeakMap(), _TokenRatesController_tokenPric
324
325
  }, {});
325
326
  });
326
327
  };
327
- /**
328
- * Create a defered Promise.
329
- *
330
- * TODO: Migrate this to utils
331
- *
332
- * @param args - The arguments.
333
- * @param args.suppressUnhandledRejection - This option adds an empty error handler
334
- * to the Promise to suppress the UnhandledPromiseRejection error. This can be
335
- * useful if the deferred Promise is sometimes intentionally not used.
336
- * @returns A deferred Promise.
337
- */
338
- function createDeferredPromise({ suppressUnhandledRejection = false, }) {
339
- let resolve;
340
- let reject;
341
- const promise = new Promise((innerResolve, innerReject) => {
342
- resolve = innerResolve;
343
- reject = innerReject;
344
- });
345
- if (suppressUnhandledRejection) {
346
- promise.catch((_error) => {
347
- // This handler is used to suppress the UnhandledPromiseRejection error
348
- });
349
- }
350
- // @ts-expect-error We know that these are assigned, but TypeScript doesn't
351
- return { promise, resolve, reject };
352
- }
353
328
  exports.default = TokenRatesController;
354
329
  //# sourceMappingURL=TokenRatesController.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TokenRatesController.js","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport {\n safelyExecute,\n toChecksumHexAddress,\n FALL_BACK_VS_CURRENCY,\n toHex,\n} from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkController,\n NetworkState,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingControllerV1 } from '@metamask/polling-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport type { Hex } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport { reduceInBatchesSerially, TOKEN_PRICES_BATCH_SIZE } from './assetsUtil';\nimport { fetchExchangeRate as fetchNativeCurrencyExchangeRate } from './crypto-compare';\nimport type { AbstractTokenPricesService } from './token-prices-service/abstract-token-prices-service';\nimport type { TokensState } from './TokensController';\n\n/**\n * @type Token\n *\n * Token representation\n * @property address - Hex address of the token contract\n * @property decimals - Number of decimals the token uses\n * @property symbol - Symbol of the token\n * @property image - Image of the token, url or bit32 image\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface Token {\n address: string;\n decimals: number;\n symbol: string;\n aggregators?: string[];\n image?: string;\n balanceError?: unknown;\n isERC721?: boolean;\n name?: string;\n}\n\n/**\n * @type TokenRatesConfig\n *\n * Token rates controller configuration\n * @property interval - Polling interval used to fetch new token rates\n * @property nativeCurrency - Current native currency selected to use base of rates\n * @property chainId - Current network chainId\n * @property tokens - List of tokens to track exchange rates for\n * @property threshold - Threshold to invalidate the supportedChains\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface TokenRatesConfig extends BaseConfig {\n interval: number;\n nativeCurrency: string;\n chainId: Hex;\n selectedAddress: string;\n allTokens: { [chainId: Hex]: { [key: string]: Token[] } };\n allDetectedTokens: { [chainId: Hex]: { [key: string]: Token[] } };\n threshold: number;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface ContractExchangeRates {\n [address: string]: number | undefined;\n}\n\nenum PollState {\n Active = 'Active',\n Inactive = 'Inactive',\n}\n\n/**\n * @type TokenRatesState\n *\n * Token rates controller state\n * @property contractExchangeRates - Hash of token contract addresses to exchange rates (single globally selected chain, will be deprecated soon)\n * @property contractExchangeRatesByChainId - Hash of token contract addresses to exchange rates keyed by chain ID and native currency (ticker)\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface TokenRatesState extends BaseState {\n contractExchangeRates: ContractExchangeRates;\n contractExchangeRatesByChainId: Record<\n Hex,\n Record<string, ContractExchangeRates>\n >;\n}\n\n/**\n * Uses the CryptoCompare API to fetch the exchange rate between one currency\n * and another, i.e., the multiplier to apply the amount of one currency in\n * order to convert it to another.\n *\n * @param args - The arguments to this function.\n * @param args.from - The currency to convert from.\n * @param args.to - The currency to convert to.\n * @returns The exchange rate between `fromCurrency` to `toCurrency` if one\n * exists, or null if one does not.\n */\nasync function getCurrencyConversionRate({\n from,\n to,\n}: {\n from: string;\n to: string;\n}) {\n const includeUSDRate = false;\n try {\n const result = await fetchNativeCurrencyExchangeRate(\n to,\n from,\n includeUSDRate,\n );\n return result.conversionRate;\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n ) {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Controller that passively polls on a set interval for token-to-fiat exchange rates\n * for tokens stored in the TokensController\n */\nexport class TokenRatesController extends StaticIntervalPollingControllerV1<\n TokenRatesConfig,\n TokenRatesState\n> {\n private handle?: ReturnType<typeof setTimeout>;\n\n #pollState = PollState.Inactive;\n\n #tokenPricesService: AbstractTokenPricesService;\n\n #inProcessExchangeRateUpdates: Record<`${Hex}:${string}`, Promise<void>> = {};\n\n /**\n * Name of this controller used during composition\n */\n override name = 'TokenRatesController';\n\n private readonly getNetworkClientById: NetworkController['getNetworkClientById'];\n\n /**\n * Creates a TokenRatesController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The polling interval in ms\n * @param options.threshold - The duration in ms before metadata fetched from CoinGecko is considered stale\n * @param options.getNetworkClientById - Gets the network client with the given id from the NetworkController.\n * @param options.chainId - The chain ID of the current network.\n * @param options.ticker - The ticker for the current network.\n * @param options.selectedAddress - The current selected address.\n * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.\n * @param options.onTokensStateChange - Allows subscribing to token controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network state changes.\n * @param options.tokenPricesService - An object in charge of retrieving token prices.\n * @param config - Initial options used to configure this controller.\n * @param state - Initial state to set on this controller.\n */\n constructor(\n {\n interval = 3 * 60 * 1000,\n threshold = 6 * 60 * 60 * 1000,\n getNetworkClientById,\n chainId: initialChainId,\n ticker: initialTicker,\n selectedAddress: initialSelectedAddress,\n onPreferencesStateChange,\n onTokensStateChange,\n onNetworkStateChange,\n tokenPricesService,\n }: {\n interval?: number;\n threshold?: number;\n getNetworkClientById: NetworkController['getNetworkClientById'];\n chainId: Hex;\n ticker: string;\n selectedAddress: string;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onTokensStateChange: (\n listener: (tokensState: TokensState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n tokenPricesService: AbstractTokenPricesService;\n },\n config?: Partial<TokenRatesConfig>,\n state?: Partial<TokenRatesState>,\n ) {\n super(config, state);\n this.defaultConfig = {\n interval,\n threshold,\n disabled: false,\n nativeCurrency: initialTicker,\n chainId: initialChainId,\n selectedAddress: initialSelectedAddress,\n allTokens: {}, // TODO: initialize these correctly, maybe as part of BaseControllerV2 migration\n allDetectedTokens: {},\n };\n\n this.defaultState = {\n contractExchangeRates: {},\n contractExchangeRatesByChainId: {},\n };\n this.initialize();\n this.setIntervalLength(interval);\n this.getNetworkClientById = getNetworkClientById;\n this.#tokenPricesService = tokenPricesService;\n\n if (config?.disabled) {\n this.configure({ disabled: true }, false, false);\n }\n\n onPreferencesStateChange(async ({ selectedAddress }) => {\n if (this.config.selectedAddress !== selectedAddress) {\n this.configure({ selectedAddress });\n if (this.#pollState === PollState.Active) {\n await this.updateExchangeRates();\n }\n }\n });\n\n onTokensStateChange(async ({ allTokens, allDetectedTokens }) => {\n const previousTokenAddresses = this.#getTokenAddresses(\n this.config.chainId,\n );\n this.configure({ allTokens, allDetectedTokens });\n const newTokenAddresses = this.#getTokenAddresses(this.config.chainId);\n if (\n !isEqual(previousTokenAddresses, newTokenAddresses) &&\n this.#pollState === PollState.Active\n ) {\n await this.updateExchangeRates();\n }\n });\n\n onNetworkStateChange(async ({ providerConfig }) => {\n const { chainId, ticker } = providerConfig;\n if (\n this.config.chainId !== chainId ||\n this.config.nativeCurrency !== ticker\n ) {\n this.update({ contractExchangeRates: {} });\n this.configure({ chainId, nativeCurrency: ticker });\n if (this.#pollState === PollState.Active) {\n await this.updateExchangeRates();\n }\n }\n });\n }\n\n /**\n * Get the user's tokens for the given chain.\n *\n * @param chainId - The chain ID.\n * @returns The list of tokens addresses for the current chain\n */\n #getTokenAddresses(chainId: Hex): Hex[] {\n const { allTokens, allDetectedTokens } = this.config;\n const tokens = allTokens[chainId]?.[this.config.selectedAddress] || [];\n const detectedTokens =\n allDetectedTokens[chainId]?.[this.config.selectedAddress] || [];\n\n return [\n ...new Set(\n [...tokens, ...detectedTokens].map((token) =>\n toHex(toChecksumHexAddress(token.address)),\n ),\n ),\n ].sort();\n }\n\n /**\n * Start (or restart) polling.\n */\n async start() {\n this.#stopPoll();\n this.#pollState = PollState.Active;\n await this.#poll();\n }\n\n /**\n * Stop polling.\n */\n stop() {\n this.#stopPoll();\n this.#pollState = PollState.Inactive;\n }\n\n /**\n * Clear the active polling timer, if present.\n */\n #stopPoll() {\n if (this.handle) {\n clearTimeout(this.handle);\n }\n }\n\n /**\n * Poll for exchange rate updates.\n */\n async #poll() {\n await safelyExecute(() => this.updateExchangeRates());\n\n // Poll using recursive `setTimeout` instead of `setInterval` so that\n // requests don't stack if they take longer than the polling interval\n this.handle = setTimeout(() => {\n this.#poll();\n }, this.config.interval);\n }\n\n /**\n * Updates exchange rates for all tokens.\n */\n async updateExchangeRates() {\n const { chainId, nativeCurrency } = this.config;\n await this.updateExchangeRatesByChainId({\n chainId,\n nativeCurrency,\n });\n }\n\n /**\n * Updates exchange rates for all tokens.\n *\n * @param options - The options to fetch exchange rates.\n * @param options.chainId - The chain ID.\n * @param options.nativeCurrency - The ticker for the chain.\n */\n async updateExchangeRatesByChainId({\n chainId,\n nativeCurrency,\n }: {\n chainId: Hex;\n nativeCurrency: string;\n }) {\n if (this.disabled) {\n return;\n }\n\n const tokenAddresses = this.#getTokenAddresses(chainId);\n if (tokenAddresses.length === 0) {\n return;\n }\n\n const updateKey: `${Hex}:${string}` = `${chainId}:${nativeCurrency}`;\n if (updateKey in this.#inProcessExchangeRateUpdates) {\n // This prevents redundant updates\n // This promise is resolved after the in-progress update has finished,\n // and state has been updated.\n await this.#inProcessExchangeRateUpdates[updateKey];\n return;\n }\n\n const {\n promise: inProgressUpdate,\n resolve: updateSucceeded,\n reject: updateFailed,\n } = createDeferredPromise({ suppressUnhandledRejection: true });\n this.#inProcessExchangeRateUpdates[updateKey] = inProgressUpdate;\n\n try {\n const newContractExchangeRates = await this.#fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n\n const existingContractExchangeRates = this.state.contractExchangeRates;\n const updatedContractExchangeRates =\n chainId === this.config.chainId &&\n nativeCurrency === this.config.nativeCurrency\n ? newContractExchangeRates\n : existingContractExchangeRates;\n\n const existingContractExchangeRatesForChainId =\n this.state.contractExchangeRatesByChainId[chainId] ?? {};\n const updatedContractExchangeRatesForChainId = {\n ...this.state.contractExchangeRatesByChainId,\n [chainId]: {\n ...existingContractExchangeRatesForChainId,\n [nativeCurrency]: {\n ...existingContractExchangeRatesForChainId[nativeCurrency],\n ...newContractExchangeRates,\n },\n },\n };\n\n this.update({\n contractExchangeRates: updatedContractExchangeRates,\n contractExchangeRatesByChainId: updatedContractExchangeRatesForChainId,\n });\n updateSucceeded();\n } catch (error: unknown) {\n updateFailed(error);\n throw error;\n } finally {\n delete this.#inProcessExchangeRateUpdates[updateKey];\n }\n }\n\n /**\n * Uses the token prices service to retrieve exchange rates for tokens in a\n * particular currency.\n *\n * If the price API does not support the given chain ID, returns an empty\n * object.\n *\n * If the price API does not support the given currency, retrieves exchange\n * rates in a known currency instead, then converts those rates using the\n * exchange rate between the known currency and desired currency.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * exchange rates.\n * @returns A map from token address to its exchange rate in the native\n * currency, or an empty map if no exchange rates can be obtained for the\n * chain ID.\n */\n async #fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractExchangeRates> {\n if (!this.#tokenPricesService.validateChainIdSupported(chainId)) {\n return tokenAddresses.reduce((obj, tokenAddress) => {\n return {\n ...obj,\n [tokenAddress]: undefined,\n };\n }, {});\n }\n\n if (this.#tokenPricesService.validateCurrencySupported(nativeCurrency)) {\n return await this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n }\n\n return await this.#fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n tokenAddresses,\n nativeCurrency,\n });\n }\n\n /**\n * Updates token rates for the given networkClientId\n *\n * @param networkClientId - The network client ID used to get a ticker value.\n * @returns The controller state.\n */\n async _executePoll(networkClientId: NetworkClientId): Promise<void> {\n const networkClient = this.getNetworkClientById(networkClientId);\n await this.updateExchangeRatesByChainId({\n chainId: networkClient.configuration.chainId,\n nativeCurrency: networkClient.configuration.ticker,\n });\n }\n\n /**\n * Retrieves prices in the given currency for the given tokens on the given\n * chain. Ensures that token addresses are checksum addresses.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractExchangeRates> {\n const tokenPricesByTokenAddress = await reduceInBatchesSerially<\n Hex,\n Awaited<ReturnType<AbstractTokenPricesService['fetchTokenPrices']>>\n >({\n values: [...tokenAddresses].sort(),\n batchSize: TOKEN_PRICES_BATCH_SIZE,\n eachBatch: async (allTokenPricesByTokenAddress, batch) => {\n const tokenPricesByTokenAddressForBatch =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: batch,\n chainId,\n currency: nativeCurrency,\n });\n\n return {\n ...allTokenPricesByTokenAddress,\n ...tokenPricesByTokenAddressForBatch,\n };\n },\n initialResult: {},\n });\n\n return Object.entries(tokenPricesByTokenAddress).reduce(\n (obj, [tokenAddress, tokenPrice]) => {\n return {\n ...obj,\n [tokenAddress]: tokenPrice?.value,\n };\n },\n {},\n );\n }\n\n /**\n * If the price API does not support a given native currency, then we need to\n * convert it to a fallback currency and feed that currency into the price\n * API, then convert the prices to our desired native currency.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n tokenAddresses,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n nativeCurrency: string;\n }): Promise<ContractExchangeRates> {\n const [\n contractExchangeRates,\n fallbackCurrencyToNativeCurrencyConversionRate,\n ] = await Promise.all([\n this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId: this.config.chainId,\n nativeCurrency: FALL_BACK_VS_CURRENCY,\n }),\n getCurrencyConversionRate({\n from: FALL_BACK_VS_CURRENCY,\n to: nativeCurrency,\n }),\n ]);\n\n if (fallbackCurrencyToNativeCurrencyConversionRate === null) {\n return {};\n }\n\n return Object.entries(contractExchangeRates).reduce(\n (obj, [tokenAddress, tokenValue]) => {\n return {\n ...obj,\n [tokenAddress]: tokenValue\n ? tokenValue * fallbackCurrencyToNativeCurrencyConversionRate\n : undefined,\n };\n },\n {},\n );\n }\n}\n\n/**\n * A deferred Promise.\n *\n * A deferred Promise is one that can be resolved or rejected independently of\n * the Promise construction.\n */\ntype DeferredPromise = {\n /**\n * The Promise that has been deferred.\n */\n promise: Promise<void>;\n /**\n * A function that resolves the Promise.\n */\n resolve: () => void;\n /**\n * A function that rejects the Promise.\n */\n reject: (error: unknown) => void;\n};\n\n/**\n * Create a defered Promise.\n *\n * TODO: Migrate this to utils\n *\n * @param args - The arguments.\n * @param args.suppressUnhandledRejection - This option adds an empty error handler\n * to the Promise to suppress the UnhandledPromiseRejection error. This can be\n * useful if the deferred Promise is sometimes intentionally not used.\n * @returns A deferred Promise.\n */\nfunction createDeferredPromise({\n suppressUnhandledRejection = false,\n}: {\n suppressUnhandledRejection: boolean;\n}): DeferredPromise {\n let resolve: DeferredPromise['resolve'];\n let reject: DeferredPromise['reject'];\n const promise = new Promise<void>(\n (innerResolve: () => void, innerReject: () => void) => {\n resolve = innerResolve;\n reject = innerReject;\n },\n );\n\n if (suppressUnhandledRejection) {\n promise.catch((_error) => {\n // This handler is used to suppress the UnhandledPromiseRejection error\n });\n }\n\n // @ts-expect-error We know that these are assigned, but TypeScript doesn't\n return { promise, resolve, reject };\n}\n\nexport default TokenRatesController;\n"]}
1
+ {"version":3,"file":"TokenRatesController.js","sourceRoot":"","sources":["../src/TokenRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport {\n safelyExecute,\n toChecksumHexAddress,\n FALL_BACK_VS_CURRENCY,\n toHex,\n} from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkController,\n NetworkState,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingControllerV1 } from '@metamask/polling-controller';\nimport type { PreferencesState } from '@metamask/preferences-controller';\nimport { createDeferredPromise, type Hex } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport { reduceInBatchesSerially, TOKEN_PRICES_BATCH_SIZE } from './assetsUtil';\nimport { fetchExchangeRate as fetchNativeCurrencyExchangeRate } from './crypto-compare';\nimport type { AbstractTokenPricesService } from './token-prices-service/abstract-token-prices-service';\nimport type { TokensState } from './TokensController';\n\n/**\n * @type Token\n *\n * Token representation\n * @property address - Hex address of the token contract\n * @property decimals - Number of decimals the token uses\n * @property symbol - Symbol of the token\n * @property image - Image of the token, url or bit32 image\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface Token {\n address: string;\n decimals: number;\n symbol: string;\n aggregators?: string[];\n image?: string;\n balanceError?: unknown;\n isERC721?: boolean;\n name?: string;\n}\n\n/**\n * @type TokenRatesConfig\n *\n * Token rates controller configuration\n * @property interval - Polling interval used to fetch new token rates\n * @property nativeCurrency - Current native currency selected to use base of rates\n * @property chainId - Current network chainId\n * @property tokens - List of tokens to track exchange rates for\n * @property threshold - Threshold to invalidate the supportedChains\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface TokenRatesConfig extends BaseConfig {\n interval: number;\n nativeCurrency: string;\n chainId: Hex;\n selectedAddress: string;\n allTokens: { [chainId: Hex]: { [key: string]: Token[] } };\n allDetectedTokens: { [chainId: Hex]: { [key: string]: Token[] } };\n threshold: number;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface ContractExchangeRates {\n [address: string]: number | undefined;\n}\n\nenum PollState {\n Active = 'Active',\n Inactive = 'Inactive',\n}\n\n/**\n * @type TokenRatesState\n *\n * Token rates controller state\n * @property contractExchangeRates - Hash of token contract addresses to exchange rates (single globally selected chain, will be deprecated soon)\n * @property contractExchangeRatesByChainId - Hash of token contract addresses to exchange rates keyed by chain ID and native currency (ticker)\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface TokenRatesState extends BaseState {\n contractExchangeRates: ContractExchangeRates;\n contractExchangeRatesByChainId: Record<\n Hex,\n Record<string, ContractExchangeRates>\n >;\n}\n\n/**\n * Uses the CryptoCompare API to fetch the exchange rate between one currency\n * and another, i.e., the multiplier to apply the amount of one currency in\n * order to convert it to another.\n *\n * @param args - The arguments to this function.\n * @param args.from - The currency to convert from.\n * @param args.to - The currency to convert to.\n * @returns The exchange rate between `fromCurrency` to `toCurrency` if one\n * exists, or null if one does not.\n */\nasync function getCurrencyConversionRate({\n from,\n to,\n}: {\n from: string;\n to: string;\n}) {\n const includeUSDRate = false;\n try {\n const result = await fetchNativeCurrencyExchangeRate(\n to,\n from,\n includeUSDRate,\n );\n return result.conversionRate;\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n ) {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Controller that passively polls on a set interval for token-to-fiat exchange rates\n * for tokens stored in the TokensController\n */\nexport class TokenRatesController extends StaticIntervalPollingControllerV1<\n TokenRatesConfig,\n TokenRatesState\n> {\n private handle?: ReturnType<typeof setTimeout>;\n\n #pollState = PollState.Inactive;\n\n #tokenPricesService: AbstractTokenPricesService;\n\n #inProcessExchangeRateUpdates: Record<`${Hex}:${string}`, Promise<void>> = {};\n\n /**\n * Name of this controller used during composition\n */\n override name = 'TokenRatesController';\n\n private readonly getNetworkClientById: NetworkController['getNetworkClientById'];\n\n /**\n * Creates a TokenRatesController instance.\n *\n * @param options - The controller options.\n * @param options.interval - The polling interval in ms\n * @param options.threshold - The duration in ms before metadata fetched from CoinGecko is considered stale\n * @param options.getNetworkClientById - Gets the network client with the given id from the NetworkController.\n * @param options.chainId - The chain ID of the current network.\n * @param options.ticker - The ticker for the current network.\n * @param options.selectedAddress - The current selected address.\n * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.\n * @param options.onTokensStateChange - Allows subscribing to token controller state changes.\n * @param options.onNetworkStateChange - Allows subscribing to network state changes.\n * @param options.tokenPricesService - An object in charge of retrieving token prices.\n * @param config - Initial options used to configure this controller.\n * @param state - Initial state to set on this controller.\n */\n constructor(\n {\n interval = 3 * 60 * 1000,\n threshold = 6 * 60 * 60 * 1000,\n getNetworkClientById,\n chainId: initialChainId,\n ticker: initialTicker,\n selectedAddress: initialSelectedAddress,\n onPreferencesStateChange,\n onTokensStateChange,\n onNetworkStateChange,\n tokenPricesService,\n }: {\n interval?: number;\n threshold?: number;\n getNetworkClientById: NetworkController['getNetworkClientById'];\n chainId: Hex;\n ticker: string;\n selectedAddress: string;\n onPreferencesStateChange: (\n listener: (preferencesState: PreferencesState) => void,\n ) => void;\n onTokensStateChange: (\n listener: (tokensState: TokensState) => void,\n ) => void;\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n tokenPricesService: AbstractTokenPricesService;\n },\n config?: Partial<TokenRatesConfig>,\n state?: Partial<TokenRatesState>,\n ) {\n super(config, state);\n this.defaultConfig = {\n interval,\n threshold,\n disabled: false,\n nativeCurrency: initialTicker,\n chainId: initialChainId,\n selectedAddress: initialSelectedAddress,\n allTokens: {}, // TODO: initialize these correctly, maybe as part of BaseControllerV2 migration\n allDetectedTokens: {},\n };\n\n this.defaultState = {\n contractExchangeRates: {},\n contractExchangeRatesByChainId: {},\n };\n this.initialize();\n this.setIntervalLength(interval);\n this.getNetworkClientById = getNetworkClientById;\n this.#tokenPricesService = tokenPricesService;\n\n if (config?.disabled) {\n this.configure({ disabled: true }, false, false);\n }\n\n onPreferencesStateChange(async ({ selectedAddress }) => {\n if (this.config.selectedAddress !== selectedAddress) {\n this.configure({ selectedAddress });\n if (this.#pollState === PollState.Active) {\n await this.updateExchangeRates();\n }\n }\n });\n\n onTokensStateChange(async ({ allTokens, allDetectedTokens }) => {\n const previousTokenAddresses = this.#getTokenAddresses(\n this.config.chainId,\n );\n this.configure({ allTokens, allDetectedTokens });\n const newTokenAddresses = this.#getTokenAddresses(this.config.chainId);\n if (\n !isEqual(previousTokenAddresses, newTokenAddresses) &&\n this.#pollState === PollState.Active\n ) {\n await this.updateExchangeRates();\n }\n });\n\n onNetworkStateChange(async ({ providerConfig }) => {\n const { chainId, ticker } = providerConfig;\n if (\n this.config.chainId !== chainId ||\n this.config.nativeCurrency !== ticker\n ) {\n this.update({ contractExchangeRates: {} });\n this.configure({ chainId, nativeCurrency: ticker });\n if (this.#pollState === PollState.Active) {\n await this.updateExchangeRates();\n }\n }\n });\n }\n\n /**\n * Get the user's tokens for the given chain.\n *\n * @param chainId - The chain ID.\n * @returns The list of tokens addresses for the current chain\n */\n #getTokenAddresses(chainId: Hex): Hex[] {\n const { allTokens, allDetectedTokens } = this.config;\n const tokens = allTokens[chainId]?.[this.config.selectedAddress] || [];\n const detectedTokens =\n allDetectedTokens[chainId]?.[this.config.selectedAddress] || [];\n\n return [\n ...new Set(\n [...tokens, ...detectedTokens].map((token) =>\n toHex(toChecksumHexAddress(token.address)),\n ),\n ),\n ].sort();\n }\n\n /**\n * Start (or restart) polling.\n */\n async start() {\n this.#stopPoll();\n this.#pollState = PollState.Active;\n await this.#poll();\n }\n\n /**\n * Stop polling.\n */\n stop() {\n this.#stopPoll();\n this.#pollState = PollState.Inactive;\n }\n\n /**\n * Clear the active polling timer, if present.\n */\n #stopPoll() {\n if (this.handle) {\n clearTimeout(this.handle);\n }\n }\n\n /**\n * Poll for exchange rate updates.\n */\n async #poll() {\n await safelyExecute(() => this.updateExchangeRates());\n\n // Poll using recursive `setTimeout` instead of `setInterval` so that\n // requests don't stack if they take longer than the polling interval\n this.handle = setTimeout(() => {\n this.#poll();\n }, this.config.interval);\n }\n\n /**\n * Updates exchange rates for all tokens.\n */\n async updateExchangeRates() {\n const { chainId, nativeCurrency } = this.config;\n await this.updateExchangeRatesByChainId({\n chainId,\n nativeCurrency,\n });\n }\n\n /**\n * Updates exchange rates for all tokens.\n *\n * @param options - The options to fetch exchange rates.\n * @param options.chainId - The chain ID.\n * @param options.nativeCurrency - The ticker for the chain.\n */\n async updateExchangeRatesByChainId({\n chainId,\n nativeCurrency,\n }: {\n chainId: Hex;\n nativeCurrency: string;\n }) {\n if (this.disabled) {\n return;\n }\n\n const tokenAddresses = this.#getTokenAddresses(chainId);\n if (tokenAddresses.length === 0) {\n return;\n }\n\n const updateKey: `${Hex}:${string}` = `${chainId}:${nativeCurrency}`;\n if (updateKey in this.#inProcessExchangeRateUpdates) {\n // This prevents redundant updates\n // This promise is resolved after the in-progress update has finished,\n // and state has been updated.\n await this.#inProcessExchangeRateUpdates[updateKey];\n return;\n }\n\n const {\n promise: inProgressUpdate,\n resolve: updateSucceeded,\n reject: updateFailed,\n } = createDeferredPromise({ suppressUnhandledRejection: true });\n this.#inProcessExchangeRateUpdates[updateKey] = inProgressUpdate;\n\n try {\n const newContractExchangeRates = await this.#fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n\n const existingContractExchangeRates = this.state.contractExchangeRates;\n const updatedContractExchangeRates =\n chainId === this.config.chainId &&\n nativeCurrency === this.config.nativeCurrency\n ? newContractExchangeRates\n : existingContractExchangeRates;\n\n const existingContractExchangeRatesForChainId =\n this.state.contractExchangeRatesByChainId[chainId] ?? {};\n const updatedContractExchangeRatesForChainId = {\n ...this.state.contractExchangeRatesByChainId,\n [chainId]: {\n ...existingContractExchangeRatesForChainId,\n [nativeCurrency]: {\n ...existingContractExchangeRatesForChainId[nativeCurrency],\n ...newContractExchangeRates,\n },\n },\n };\n\n this.update({\n contractExchangeRates: updatedContractExchangeRates,\n contractExchangeRatesByChainId: updatedContractExchangeRatesForChainId,\n });\n updateSucceeded();\n } catch (error: unknown) {\n updateFailed(error);\n throw error;\n } finally {\n delete this.#inProcessExchangeRateUpdates[updateKey];\n }\n }\n\n /**\n * Uses the token prices service to retrieve exchange rates for tokens in a\n * particular currency.\n *\n * If the price API does not support the given chain ID, returns an empty\n * object.\n *\n * If the price API does not support the given currency, retrieves exchange\n * rates in a known currency instead, then converts those rates using the\n * exchange rate between the known currency and desired currency.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * exchange rates.\n * @returns A map from token address to its exchange rate in the native\n * currency, or an empty map if no exchange rates can be obtained for the\n * chain ID.\n */\n async #fetchAndMapExchangeRates({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractExchangeRates> {\n if (!this.#tokenPricesService.validateChainIdSupported(chainId)) {\n return tokenAddresses.reduce((obj, tokenAddress) => {\n return {\n ...obj,\n [tokenAddress]: undefined,\n };\n }, {});\n }\n\n if (this.#tokenPricesService.validateCurrencySupported(nativeCurrency)) {\n return await this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n });\n }\n\n return await this.#fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n tokenAddresses,\n nativeCurrency,\n });\n }\n\n /**\n * Updates token rates for the given networkClientId\n *\n * @param networkClientId - The network client ID used to get a ticker value.\n * @returns The controller state.\n */\n async _executePoll(networkClientId: NetworkClientId): Promise<void> {\n const networkClient = this.getNetworkClientById(networkClientId);\n await this.updateExchangeRatesByChainId({\n chainId: networkClient.configuration.chainId,\n nativeCurrency: networkClient.configuration.ticker,\n });\n }\n\n /**\n * Retrieves prices in the given currency for the given tokens on the given\n * chain. Ensures that token addresses are checksum addresses.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.chainId - The EIP-155 ID of the chain where the tokens live.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n chainId: Hex;\n nativeCurrency: string;\n }): Promise<ContractExchangeRates> {\n const tokenPricesByTokenAddress = await reduceInBatchesSerially<\n Hex,\n Awaited<ReturnType<AbstractTokenPricesService['fetchTokenPrices']>>\n >({\n values: [...tokenAddresses].sort(),\n batchSize: TOKEN_PRICES_BATCH_SIZE,\n eachBatch: async (allTokenPricesByTokenAddress, batch) => {\n const tokenPricesByTokenAddressForBatch =\n await this.#tokenPricesService.fetchTokenPrices({\n tokenAddresses: batch,\n chainId,\n currency: nativeCurrency,\n });\n\n return {\n ...allTokenPricesByTokenAddress,\n ...tokenPricesByTokenAddressForBatch,\n };\n },\n initialResult: {},\n });\n\n return Object.entries(tokenPricesByTokenAddress).reduce(\n (obj, [tokenAddress, tokenPrice]) => {\n return {\n ...obj,\n [tokenAddress]: tokenPrice?.value,\n };\n },\n {},\n );\n }\n\n /**\n * If the price API does not support a given native currency, then we need to\n * convert it to a fallback currency and feed that currency into the price\n * API, then convert the prices to our desired native currency.\n *\n * @param args - The arguments to this function.\n * @param args.tokenAddresses - Addresses for tokens.\n * @param args.nativeCurrency - The native currency in which to request\n * prices.\n * @returns A map of the token addresses (as checksums) to their prices in the\n * native currency.\n */\n async #fetchAndMapExchangeRatesForUnsupportedNativeCurrency({\n tokenAddresses,\n nativeCurrency,\n }: {\n tokenAddresses: Hex[];\n nativeCurrency: string;\n }): Promise<ContractExchangeRates> {\n const [\n contractExchangeRates,\n fallbackCurrencyToNativeCurrencyConversionRate,\n ] = await Promise.all([\n this.#fetchAndMapExchangeRatesForSupportedNativeCurrency({\n tokenAddresses,\n chainId: this.config.chainId,\n nativeCurrency: FALL_BACK_VS_CURRENCY,\n }),\n getCurrencyConversionRate({\n from: FALL_BACK_VS_CURRENCY,\n to: nativeCurrency,\n }),\n ]);\n\n if (fallbackCurrencyToNativeCurrencyConversionRate === null) {\n return {};\n }\n\n return Object.entries(contractExchangeRates).reduce(\n (obj, [tokenAddress, tokenValue]) => {\n return {\n ...obj,\n [tokenAddress]: tokenValue\n ? tokenValue * fallbackCurrencyToNativeCurrencyConversionRate\n : undefined,\n };\n },\n {},\n );\n }\n}\n\nexport default TokenRatesController;\n"]}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,8 @@ export * from './AssetsContractController';
3
3
  export * from './CurrencyRateController';
4
4
  export * from './NftController';
5
5
  export * from './NftDetectionController';
6
- export * from './TokenBalancesController';
6
+ export type { TokenBalancesControllerMessenger, TokenBalancesControllerActions, TokenBalancesControllerGetStateAction, TokenBalancesControllerEvents, TokenBalancesControllerStateChangeEvent, } from './TokenBalancesController';
7
+ export { TokenBalancesController } from './TokenBalancesController';
7
8
  export type { TokenDetectionControllerMessenger, TokenDetectionControllerActions, TokenDetectionControllerGetStateAction, TokenDetectionControllerEvents, TokenDetectionControllerStateChangeEvent, } from './TokenDetectionController';
8
9
  export { TokenDetectionController } from './TokenDetectionController';
9
10
  export * from './TokenListController';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,YAAY,EACV,iCAAiC,EACjC,+BAA+B,EAC/B,sCAAsC,EACtC,8BAA8B,EAC9B,wCAAwC,GACzC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EACL,mCAAmC,EACnC,sBAAsB,EACtB,mBAAmB,EACnB,+BAA+B,GAChC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,YAAY,EACV,gCAAgC,EAChC,8BAA8B,EAC9B,qCAAqC,EACrC,6BAA6B,EAC7B,uCAAuC,GACxC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,YAAY,EACV,iCAAiC,EACjC,+BAA+B,EAC/B,sCAAsC,EACtC,8BAA8B,EAC9B,wCAAwC,GACzC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EACL,mCAAmC,EACnC,sBAAsB,EACtB,mBAAmB,EACnB,+BAA+B,GAChC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -14,13 +14,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.CodefiTokenPricesServiceV2 = exports.fetchTokenContractExchangeRates = exports.getFormattedIpfsUrl = exports.formatIconUrlWithProxy = exports.isTokenDetectionSupportedForNetwork = exports.TokenDetectionController = void 0;
17
+ exports.CodefiTokenPricesServiceV2 = exports.fetchTokenContractExchangeRates = exports.getFormattedIpfsUrl = exports.formatIconUrlWithProxy = exports.isTokenDetectionSupportedForNetwork = exports.TokenDetectionController = exports.TokenBalancesController = void 0;
18
18
  __exportStar(require("./AccountTrackerController"), exports);
19
19
  __exportStar(require("./AssetsContractController"), exports);
20
20
  __exportStar(require("./CurrencyRateController"), exports);
21
21
  __exportStar(require("./NftController"), exports);
22
22
  __exportStar(require("./NftDetectionController"), exports);
23
- __exportStar(require("./TokenBalancesController"), exports);
23
+ var TokenBalancesController_1 = require("./TokenBalancesController");
24
+ Object.defineProperty(exports, "TokenBalancesController", { enumerable: true, get: function () { return TokenBalancesController_1.TokenBalancesController; } });
24
25
  var TokenDetectionController_1 = require("./TokenDetectionController");
25
26
  Object.defineProperty(exports, "TokenDetectionController", { enumerable: true, get: function () { return TokenDetectionController_1.TokenDetectionController; } });
26
27
  __exportStar(require("./TokenListController"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAA2C;AAC3C,6DAA2C;AAC3C,2DAAyC;AACzC,kDAAgC;AAChC,2DAAyC;AACzC,4DAA0C;AAQ1C,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA;AACjC,wDAAsC;AACtC,yDAAuC;AACvC,qDAAmC;AACnC,2CAKsB;AAJpB,iIAAA,mCAAmC,OAAA;AACnC,oHAAA,sBAAsB,OAAA;AACtB,iHAAA,mBAAmB,OAAA;AACnB,6HAAA,+BAA+B,OAAA;AAEjC,+DAAoE;AAA3D,kIAAA,0BAA0B,OAAA","sourcesContent":["export * from './AccountTrackerController';\nexport * from './AssetsContractController';\nexport * from './CurrencyRateController';\nexport * from './NftController';\nexport * from './NftDetectionController';\nexport * from './TokenBalancesController';\nexport type {\n TokenDetectionControllerMessenger,\n TokenDetectionControllerActions,\n TokenDetectionControllerGetStateAction,\n TokenDetectionControllerEvents,\n TokenDetectionControllerStateChangeEvent,\n} from './TokenDetectionController';\nexport { TokenDetectionController } from './TokenDetectionController';\nexport * from './TokenListController';\nexport * from './TokenRatesController';\nexport * from './TokensController';\nexport {\n isTokenDetectionSupportedForNetwork,\n formatIconUrlWithProxy,\n getFormattedIpfsUrl,\n fetchTokenContractExchangeRates,\n} from './assetsUtil';\nexport { CodefiTokenPricesServiceV2 } from './token-prices-service';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAA2C;AAC3C,6DAA2C;AAC3C,2DAAyC;AACzC,kDAAgC;AAChC,2DAAyC;AAQzC,qEAAoE;AAA3D,kIAAA,uBAAuB,OAAA;AAQhC,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA;AACjC,wDAAsC;AACtC,yDAAuC;AACvC,qDAAmC;AACnC,2CAKsB;AAJpB,iIAAA,mCAAmC,OAAA;AACnC,oHAAA,sBAAsB,OAAA;AACtB,iHAAA,mBAAmB,OAAA;AACnB,6HAAA,+BAA+B,OAAA;AAEjC,+DAAoE;AAA3D,kIAAA,0BAA0B,OAAA","sourcesContent":["export * from './AccountTrackerController';\nexport * from './AssetsContractController';\nexport * from './CurrencyRateController';\nexport * from './NftController';\nexport * from './NftDetectionController';\nexport type {\n TokenBalancesControllerMessenger,\n TokenBalancesControllerActions,\n TokenBalancesControllerGetStateAction,\n TokenBalancesControllerEvents,\n TokenBalancesControllerStateChangeEvent,\n} from './TokenBalancesController';\nexport { TokenBalancesController } from './TokenBalancesController';\nexport type {\n TokenDetectionControllerMessenger,\n TokenDetectionControllerActions,\n TokenDetectionControllerGetStateAction,\n TokenDetectionControllerEvents,\n TokenDetectionControllerStateChangeEvent,\n} from './TokenDetectionController';\nexport { TokenDetectionController } from './TokenDetectionController';\nexport * from './TokenListController';\nexport * from './TokenRatesController';\nexport * from './TokensController';\nexport {\n isTokenDetectionSupportedForNetwork,\n formatIconUrlWithProxy,\n getFormattedIpfsUrl,\n fetchTokenContractExchangeRates,\n} from './assetsUtil';\nexport { CodefiTokenPricesServiceV2 } from './token-prices-service';\n"]}
@@ -15,7 +15,7 @@ declare type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number] | Upperca
15
15
  * endpoint, but in hexadecimal form (for consistency with how we represent
16
16
  * chain IDs in other places).
17
17
  */
18
- export declare const SUPPORTED_CHAIN_IDS: readonly ["0x1", "0xa", "0x19", "0x38", "0x39", "0x42", "0x46", "0x52", "0x58", "0x64", "0x6a", "0x7a", "0x80", "0x89", "0xfa", "0x120", "0x141", "0x144", "0x169", "0x440", "0x504", "0x505", "0x2105", "0x150", "0x2710", "0xa4b1", "0xa4ec", "0xa516", "0xa86a", "0x518af", "0x4e454152", "0x63564c40"];
18
+ export declare const SUPPORTED_CHAIN_IDS: readonly ["0x1", "0xa", "0x19", "0x38", "0x39", "0x42", "0x46", "0x52", "0x58", "0x64", "0x6a", "0x7a", "0x80", "0x89", "0xfa", "0x120", "0x141", "0x144", "0x169", "0x440", "0x504", "0x505", "0x2105", "0x150", "0x2710", "0xa4b1", "0xa4ec", "0xa516", "0xa86a", "0x518af", "0x4e454152", "0x63564c40", "0xe708"];
19
19
  /**
20
20
  * A chain ID that can be supplied in the URL for the `/spot-prices` endpoint,
21
21
  * but in hexadecimal form (for consistency with how we represent chain IDs in
@@ -1 +1 @@
1
- {"version":3,"file":"codefi-v2.d.ts","sourceRoot":"","sources":["../../src/token-prices-service/codefi-v2.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAa3C,OAAO,KAAK,EACV,0BAA0B,EAE1B,yBAAyB,EAC1B,MAAM,iCAAiC,CAAC;AAUzC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,ybA2HvB,CAAC;AAEX;;;GAGG;AACH,aAAK,iBAAiB,GAClB,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,GACrC,SAAS,CAAC,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,4SAiEtB,CAAC;AAEX;;;;GAIG;AACH,aAAK,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAc7D;;;GAGG;AACH,qBAAa,0BACX,YACE,0BAA0B,CAAC,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,CAAC;;IAItE;;;;;;;;;;;;;;;OAeG;gBACS,EACV,iBAA8C,EAC9C,OAAqC,EACrC,0BAAyE,EACzE,OAAO,EACP,UAAU,EACV,oBAAqC,GACtC,GAAE;QACD,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,0BAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;QACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC1B;IAgCN;;;;;;;;;OASG;IACG,gBAAgB,CAAC,EACrB,OAAO,EACP,cAAc,EACd,QAAQ,GACT,EAAE;QACD,OAAO,EAAE,gBAAgB,CAAC;QAC1B,cAAc,EAAE,GAAG,EAAE,CAAC;QACtB,QAAQ,EAAE,iBAAiB,CAAC;KAC7B,GAAG,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAqDvE;;;;;;OAMG;IACH,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB;IAKvE;;;;;;;OAOG;IACH,yBAAyB,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,IAAI,iBAAiB;CAO5E"}
1
+ {"version":3,"file":"codefi-v2.d.ts","sourceRoot":"","sources":["../../src/token-prices-service/codefi-v2.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAa3C,OAAO,KAAK,EACV,0BAA0B,EAE1B,yBAAyB,EAC1B,MAAM,iCAAiC,CAAC;AAUzC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,ybA2HvB,CAAC;AAEX;;;GAGG;AACH,aAAK,iBAAiB,GAClB,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,GACrC,SAAS,CAAC,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,sTAmEtB,CAAC;AAEX;;;;GAIG;AACH,aAAK,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAc7D;;;GAGG;AACH,qBAAa,0BACX,YACE,0BAA0B,CAAC,gBAAgB,EAAE,GAAG,EAAE,iBAAiB,CAAC;;IAItE;;;;;;;;;;;;;;;OAeG;gBACS,EACV,iBAA8C,EAC9C,OAAqC,EACrC,0BAAyE,EACzE,OAAO,EACP,UAAU,EACV,oBAAqC,GACtC,GAAE;QACD,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,0BAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;QACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC1B;IAgCN;;;;;;;;;OASG;IACG,gBAAgB,CAAC,EACrB,OAAO,EACP,cAAc,EACd,QAAQ,GACT,EAAE;QACD,OAAO,EAAE,gBAAgB,CAAC;QAC1B,cAAc,EAAE,GAAG,EAAE,CAAC;QACtB,QAAQ,EAAE,iBAAiB,CAAC;KAC7B,GAAG,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAqDvE;;;;;;OAMG;IACH,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB;IAKvE;;;;;;;OAOG;IACH,yBAAyB,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,IAAI,iBAAiB;CAO5E"}
@@ -223,6 +223,8 @@ exports.SUPPORTED_CHAIN_IDS = [
223
223
  '0x4e454152',
224
224
  // Harmony Mainnet Shard 0
225
225
  '0x63564c40',
226
+ // Linea Mainnet
227
+ '0xe708',
226
228
  ];
227
229
  /**
228
230
  * All requests to V2 of the Price API start with this.
@@ -1 +1 @@
1
- {"version":3,"file":"codefi-v2.js","sourceRoot":"","sources":["../../src/token-prices-service/codefi-v2.ts"],"names":[],"mappings":"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","sourcesContent":["import { handleFetch } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { hexToNumber } from '@metamask/utils';\nimport {\n circuitBreaker,\n ConsecutiveBreaker,\n ExponentialBackoff,\n handleAll,\n type IPolicy,\n retry,\n wrap,\n CircuitState,\n} from 'cockatiel';\n\nimport type {\n AbstractTokenPricesService,\n TokenPrice,\n TokenPricesByTokenAddress,\n} from './abstract-token-prices-service';\n\n/**\n * The shape of the data that the /spot-prices endpoint returns.\n */\ntype SpotPricesEndpointData<\n TokenAddress extends Hex,\n Currency extends string,\n> = Record<TokenAddress, Record<Currency, number>>;\n\n/**\n * The list of currencies that can be supplied as the `vsCurrency` parameter to\n * the `/spot-prices` endpoint, in lowercase form.\n */\nexport const SUPPORTED_CURRENCIES = [\n // Bitcoin\n 'btc',\n // Ether\n 'eth',\n // Litecoin\n 'ltc',\n // Bitcoin Cash\n 'bch',\n // Binance Coin\n 'bnb',\n // EOS\n 'eos',\n // XRP\n 'xrp',\n // Lumens\n 'xlm',\n // Chainlink\n 'link',\n // Polkadot\n 'dot',\n // Yearn.finance\n 'yfi',\n // US Dollar\n 'usd',\n // United Arab Emirates Dirham\n 'aed',\n // Argentine Peso\n 'ars',\n // Australian Dollar\n 'aud',\n // Bangladeshi Taka\n 'bdt',\n // Bahraini Dinar\n 'bhd',\n // Bermudian Dollar\n 'bmd',\n // Brazil Real\n 'brl',\n // Canadian Dollar\n 'cad',\n // Swiss Franc\n 'chf',\n // Chilean Peso\n 'clp',\n // Chinese Yuan\n 'cny',\n // Czech Koruna\n 'czk',\n // Danish Krone\n 'dkk',\n // Euro\n 'eur',\n // British Pound Sterling\n 'gbp',\n // Hong Kong Dollar\n 'hkd',\n // Hungarian Forint\n 'huf',\n // Indonesian Rupiah\n 'idr',\n // Israeli New Shekel\n 'ils',\n // Indian Rupee\n 'inr',\n // Japanese Yen\n 'jpy',\n // South Korean Won\n 'krw',\n // Kuwaiti Dinar\n 'kwd',\n // Sri Lankan Rupee\n 'lkr',\n // Burmese Kyat\n 'mmk',\n // Mexican Peso\n 'mxn',\n // Malaysian Ringgit\n 'myr',\n // Nigerian Naira\n 'ngn',\n // Norwegian Krone\n 'nok',\n // New Zealand Dollar\n 'nzd',\n // Philippine Peso\n 'php',\n // Pakistani Rupee\n 'pkr',\n // Polish Zloty\n 'pln',\n // Russian Ruble\n 'rub',\n // Saudi Riyal\n 'sar',\n // Swedish Krona\n 'sek',\n // Singapore Dollar\n 'sgd',\n // Thai Baht\n 'thb',\n // Turkish Lira\n 'try',\n // New Taiwan Dollar\n 'twd',\n // Ukrainian hryvnia\n 'uah',\n // Venezuelan bolívar fuerte\n 'vef',\n // Vietnamese đồng\n 'vnd',\n // South African Rand\n 'zar',\n // IMF Special Drawing Rights\n 'xdr',\n // Silver - Troy Ounce\n 'xag',\n // Gold - Troy Ounce\n 'xau',\n // Bits\n 'bits',\n // Satoshi\n 'sats',\n] as const;\n\n/**\n * A currency that can be supplied as the `vsCurrency` parameter to\n * the `/spot-prices` endpoint. Covers both uppercase and lowercase versions.\n */\ntype SupportedCurrency =\n | (typeof SUPPORTED_CURRENCIES)[number]\n | Uppercase<(typeof SUPPORTED_CURRENCIES)[number]>;\n\n/**\n * The list of chain IDs that can be supplied in the URL for the `/spot-prices`\n * endpoint, but in hexadecimal form (for consistency with how we represent\n * chain IDs in other places).\n */\nexport const SUPPORTED_CHAIN_IDS = [\n // Ethereum Mainnet\n '0x1',\n // OP Mainnet\n '0xa',\n // Cronos Mainnet\n '0x19',\n // BNB Smart Chain Mainnet\n '0x38',\n // Syscoin Mainnet\n '0x39',\n // OKXChain Mainnet\n '0x42',\n // Hoo Smart Chain\n '0x46',\n // Meter Mainnet\n '0x52',\n // TomoChain\n '0x58',\n // Gnosis\n '0x64',\n // Velas EVM Mainnet\n '0x6a',\n // Fuse Mainnet\n '0x7a',\n // Huobi ECO Chain Mainnet\n '0x80',\n // Polygon Mainnet\n '0x89',\n // Fantom Opera\n '0xfa',\n // Boba Network\n '0x120',\n // KCC Mainnet\n '0x141',\n // zkSync Era Mainnet\n '0x144',\n // Theta Mainnet\n '0x169',\n // Metis Andromeda Mainnet\n '0x440',\n // Moonbeam\n '0x504',\n // Moonriver\n '0x505',\n // Base\n '0x2105',\n // Shiden\n '0x150',\n // Smart Bitcoin Cash\n '0x2710',\n // Arbitrum One\n '0xa4b1',\n // Celo Mainnet\n '0xa4ec',\n // Oasis Emerald\n '0xa516',\n // Avalanche C-Chain\n '0xa86a',\n // Polis Mainnet\n '0x518af',\n // Aurora Mainnet\n '0x4e454152',\n // Harmony Mainnet Shard 0\n '0x63564c40',\n] as const;\n\n/**\n * A chain ID that can be supplied in the URL for the `/spot-prices` endpoint,\n * but in hexadecimal form (for consistency with how we represent chain IDs in\n * other places).\n */\ntype SupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];\n\n/**\n * All requests to V2 of the Price API start with this.\n */\nconst BASE_URL = 'https://price-api.metafi.codefi.network/v2';\n\nconst DEFAULT_TOKEN_PRICE_RETRIES = 3;\n// Each update attempt will result (1 + retries) calls if the server is down\nconst DEFAULT_TOKEN_PRICE_MAX_CONSECUTIVE_FAILURES =\n (1 + DEFAULT_TOKEN_PRICE_RETRIES) * 3;\n\nconst DEFAULT_DEGRADED_THRESHOLD = 5_000;\n\n/**\n * This version of the token prices service uses V2 of the Codefi Price API to\n * fetch token prices.\n */\nexport class CodefiTokenPricesServiceV2\n implements\n AbstractTokenPricesService<SupportedChainId, Hex, SupportedCurrency>\n{\n #tokenPricePolicy: IPolicy;\n\n /**\n * Construct a Codefi Token Price Service.\n *\n * @param options - Constructor options\n * @param options.degradedThreshold - The threshold between \"normal\" and \"degrated\" service,\n * in milliseconds.\n * @param options.retries - Number of retry attempts for each token price update.\n * @param options.maximumConsecutiveFailures - The maximum number of consecutive failures\n * allowed before breaking the circuit and pausing further updates.\n * @param options.onBreak - An event handler for when the circuit breaks, useful for capturing\n * metrics about network failures.\n * @param options.onDegraded - An event handler for when the circuit remains closed, but requests\n * are failing or resolving too slowly (i.e. resolving more slowly than the `degradedThreshold).\n * @param options.circuitBreakDuration - The amount of time to wait when the circuit breaks\n * from too many consecutive failures.\n */\n constructor({\n degradedThreshold = DEFAULT_DEGRADED_THRESHOLD,\n retries = DEFAULT_TOKEN_PRICE_RETRIES,\n maximumConsecutiveFailures = DEFAULT_TOKEN_PRICE_MAX_CONSECUTIVE_FAILURES,\n onBreak,\n onDegraded,\n circuitBreakDuration = 30 * 60 * 1000,\n }: {\n degradedThreshold?: number;\n retries?: number;\n maximumConsecutiveFailures?: number;\n onBreak?: () => void;\n onDegraded?: () => void;\n circuitBreakDuration?: number;\n } = {}) {\n // Construct a policy that will retry each update, and halt further updates\n // for a certain period after too many consecutive failures.\n const retryPolicy = retry(handleAll, {\n maxAttempts: retries,\n backoff: new ExponentialBackoff(),\n });\n const circuitBreakerPolicy = circuitBreaker(handleAll, {\n halfOpenAfter: circuitBreakDuration,\n breaker: new ConsecutiveBreaker(maximumConsecutiveFailures),\n });\n if (onBreak) {\n circuitBreakerPolicy.onBreak(onBreak);\n }\n if (onDegraded) {\n retryPolicy.onGiveUp(() => {\n if (circuitBreakerPolicy.state === CircuitState.Closed) {\n onDegraded();\n }\n });\n retryPolicy.onSuccess(({ duration }) => {\n if (\n circuitBreakerPolicy.state === CircuitState.Closed &&\n duration > degradedThreshold\n ) {\n onDegraded();\n }\n });\n }\n this.#tokenPricePolicy = wrap(retryPolicy, circuitBreakerPolicy);\n }\n\n /**\n * Retrieves prices in the given currency for the tokens identified by the\n * given addresses which are expected to live on the given chain.\n *\n * @param args - The arguments to function.\n * @param args.chainId - An EIP-155 chain ID.\n * @param args.tokenAddresses - Addresses for tokens that live on the chain.\n * @param args.currency - The desired currency of the token prices.\n * @returns The prices for the requested tokens.\n */\n async fetchTokenPrices({\n chainId,\n tokenAddresses,\n currency,\n }: {\n chainId: SupportedChainId;\n tokenAddresses: Hex[];\n currency: SupportedCurrency;\n }): Promise<Partial<TokenPricesByTokenAddress<Hex, SupportedCurrency>>> {\n const chainIdAsNumber = hexToNumber(chainId);\n\n const url = new URL(`${BASE_URL}/chains/${chainIdAsNumber}/spot-prices`);\n url.searchParams.append('tokenAddresses', tokenAddresses.join(','));\n url.searchParams.append('vsCurrency', currency);\n\n const pricesByCurrencyByTokenAddress: SpotPricesEndpointData<\n Lowercase<Hex>,\n Lowercase<SupportedCurrency>\n > = await this.#tokenPricePolicy.execute(() => handleFetch(url));\n\n return tokenAddresses.reduce(\n (\n obj: Partial<TokenPricesByTokenAddress<Hex, SupportedCurrency>>,\n tokenAddress,\n ) => {\n // The Price API lowercases both currency and token addresses, so we have\n // to keep track of them and make sure we return the original versions.\n const lowercasedTokenAddress =\n tokenAddress.toLowerCase() as Lowercase<Hex>;\n const lowercasedCurrency =\n currency.toLowerCase() as Lowercase<SupportedCurrency>;\n\n const price =\n pricesByCurrencyByTokenAddress[lowercasedTokenAddress]?.[\n lowercasedCurrency\n ];\n\n if (!price) {\n // console error instead of throwing to not interrupt the fetching of other tokens in case just one fails\n console.error(\n `Could not find price for \"${tokenAddress}\" in \"${currency}\"`,\n );\n }\n\n const tokenPrice: TokenPrice<Hex, SupportedCurrency> = {\n tokenAddress,\n value: price,\n currency,\n };\n\n return {\n ...obj,\n ...(tokenPrice.value !== undefined\n ? { [tokenAddress]: tokenPrice }\n : {}),\n };\n },\n {},\n ) as Partial<TokenPricesByTokenAddress<Hex, SupportedCurrency>>;\n }\n\n /**\n * Type guard for whether the API can return token prices for the given chain\n * ID.\n *\n * @param chainId - The chain ID to check.\n * @returns True if the API supports the chain ID, false otherwise.\n */\n validateChainIdSupported(chainId: unknown): chainId is SupportedChainId {\n const supportedChainIds: readonly string[] = SUPPORTED_CHAIN_IDS;\n return typeof chainId === 'string' && supportedChainIds.includes(chainId);\n }\n\n /**\n * Type guard for whether the API can return token prices in the given\n * currency.\n *\n * @param currency - The currency to check. If a string, can be either\n * lowercase or uppercase.\n * @returns True if the API supports the currency, false otherwise.\n */\n validateCurrencySupported(currency: unknown): currency is SupportedCurrency {\n const supportedCurrencies: readonly string[] = SUPPORTED_CURRENCIES;\n return (\n typeof currency === 'string' &&\n supportedCurrencies.includes(currency.toLowerCase())\n );\n }\n}\n"]}
1
+ {"version":3,"file":"codefi-v2.js","sourceRoot":"","sources":["../../src/token-prices-service/codefi-v2.ts"],"names":[],"mappings":"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","sourcesContent":["import { handleFetch } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { hexToNumber } from '@metamask/utils';\nimport {\n circuitBreaker,\n ConsecutiveBreaker,\n ExponentialBackoff,\n handleAll,\n type IPolicy,\n retry,\n wrap,\n CircuitState,\n} from 'cockatiel';\n\nimport type {\n AbstractTokenPricesService,\n TokenPrice,\n TokenPricesByTokenAddress,\n} from './abstract-token-prices-service';\n\n/**\n * The shape of the data that the /spot-prices endpoint returns.\n */\ntype SpotPricesEndpointData<\n TokenAddress extends Hex,\n Currency extends string,\n> = Record<TokenAddress, Record<Currency, number>>;\n\n/**\n * The list of currencies that can be supplied as the `vsCurrency` parameter to\n * the `/spot-prices` endpoint, in lowercase form.\n */\nexport const SUPPORTED_CURRENCIES = [\n // Bitcoin\n 'btc',\n // Ether\n 'eth',\n // Litecoin\n 'ltc',\n // Bitcoin Cash\n 'bch',\n // Binance Coin\n 'bnb',\n // EOS\n 'eos',\n // XRP\n 'xrp',\n // Lumens\n 'xlm',\n // Chainlink\n 'link',\n // Polkadot\n 'dot',\n // Yearn.finance\n 'yfi',\n // US Dollar\n 'usd',\n // United Arab Emirates Dirham\n 'aed',\n // Argentine Peso\n 'ars',\n // Australian Dollar\n 'aud',\n // Bangladeshi Taka\n 'bdt',\n // Bahraini Dinar\n 'bhd',\n // Bermudian Dollar\n 'bmd',\n // Brazil Real\n 'brl',\n // Canadian Dollar\n 'cad',\n // Swiss Franc\n 'chf',\n // Chilean Peso\n 'clp',\n // Chinese Yuan\n 'cny',\n // Czech Koruna\n 'czk',\n // Danish Krone\n 'dkk',\n // Euro\n 'eur',\n // British Pound Sterling\n 'gbp',\n // Hong Kong Dollar\n 'hkd',\n // Hungarian Forint\n 'huf',\n // Indonesian Rupiah\n 'idr',\n // Israeli New Shekel\n 'ils',\n // Indian Rupee\n 'inr',\n // Japanese Yen\n 'jpy',\n // South Korean Won\n 'krw',\n // Kuwaiti Dinar\n 'kwd',\n // Sri Lankan Rupee\n 'lkr',\n // Burmese Kyat\n 'mmk',\n // Mexican Peso\n 'mxn',\n // Malaysian Ringgit\n 'myr',\n // Nigerian Naira\n 'ngn',\n // Norwegian Krone\n 'nok',\n // New Zealand Dollar\n 'nzd',\n // Philippine Peso\n 'php',\n // Pakistani Rupee\n 'pkr',\n // Polish Zloty\n 'pln',\n // Russian Ruble\n 'rub',\n // Saudi Riyal\n 'sar',\n // Swedish Krona\n 'sek',\n // Singapore Dollar\n 'sgd',\n // Thai Baht\n 'thb',\n // Turkish Lira\n 'try',\n // New Taiwan Dollar\n 'twd',\n // Ukrainian hryvnia\n 'uah',\n // Venezuelan bolívar fuerte\n 'vef',\n // Vietnamese đồng\n 'vnd',\n // South African Rand\n 'zar',\n // IMF Special Drawing Rights\n 'xdr',\n // Silver - Troy Ounce\n 'xag',\n // Gold - Troy Ounce\n 'xau',\n // Bits\n 'bits',\n // Satoshi\n 'sats',\n] as const;\n\n/**\n * A currency that can be supplied as the `vsCurrency` parameter to\n * the `/spot-prices` endpoint. Covers both uppercase and lowercase versions.\n */\ntype SupportedCurrency =\n | (typeof SUPPORTED_CURRENCIES)[number]\n | Uppercase<(typeof SUPPORTED_CURRENCIES)[number]>;\n\n/**\n * The list of chain IDs that can be supplied in the URL for the `/spot-prices`\n * endpoint, but in hexadecimal form (for consistency with how we represent\n * chain IDs in other places).\n */\nexport const SUPPORTED_CHAIN_IDS = [\n // Ethereum Mainnet\n '0x1',\n // OP Mainnet\n '0xa',\n // Cronos Mainnet\n '0x19',\n // BNB Smart Chain Mainnet\n '0x38',\n // Syscoin Mainnet\n '0x39',\n // OKXChain Mainnet\n '0x42',\n // Hoo Smart Chain\n '0x46',\n // Meter Mainnet\n '0x52',\n // TomoChain\n '0x58',\n // Gnosis\n '0x64',\n // Velas EVM Mainnet\n '0x6a',\n // Fuse Mainnet\n '0x7a',\n // Huobi ECO Chain Mainnet\n '0x80',\n // Polygon Mainnet\n '0x89',\n // Fantom Opera\n '0xfa',\n // Boba Network\n '0x120',\n // KCC Mainnet\n '0x141',\n // zkSync Era Mainnet\n '0x144',\n // Theta Mainnet\n '0x169',\n // Metis Andromeda Mainnet\n '0x440',\n // Moonbeam\n '0x504',\n // Moonriver\n '0x505',\n // Base\n '0x2105',\n // Shiden\n '0x150',\n // Smart Bitcoin Cash\n '0x2710',\n // Arbitrum One\n '0xa4b1',\n // Celo Mainnet\n '0xa4ec',\n // Oasis Emerald\n '0xa516',\n // Avalanche C-Chain\n '0xa86a',\n // Polis Mainnet\n '0x518af',\n // Aurora Mainnet\n '0x4e454152',\n // Harmony Mainnet Shard 0\n '0x63564c40',\n // Linea Mainnet\n '0xe708',\n] as const;\n\n/**\n * A chain ID that can be supplied in the URL for the `/spot-prices` endpoint,\n * but in hexadecimal form (for consistency with how we represent chain IDs in\n * other places).\n */\ntype SupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number];\n\n/**\n * All requests to V2 of the Price API start with this.\n */\nconst BASE_URL = 'https://price-api.metafi.codefi.network/v2';\n\nconst DEFAULT_TOKEN_PRICE_RETRIES = 3;\n// Each update attempt will result (1 + retries) calls if the server is down\nconst DEFAULT_TOKEN_PRICE_MAX_CONSECUTIVE_FAILURES =\n (1 + DEFAULT_TOKEN_PRICE_RETRIES) * 3;\n\nconst DEFAULT_DEGRADED_THRESHOLD = 5_000;\n\n/**\n * This version of the token prices service uses V2 of the Codefi Price API to\n * fetch token prices.\n */\nexport class CodefiTokenPricesServiceV2\n implements\n AbstractTokenPricesService<SupportedChainId, Hex, SupportedCurrency>\n{\n #tokenPricePolicy: IPolicy;\n\n /**\n * Construct a Codefi Token Price Service.\n *\n * @param options - Constructor options\n * @param options.degradedThreshold - The threshold between \"normal\" and \"degrated\" service,\n * in milliseconds.\n * @param options.retries - Number of retry attempts for each token price update.\n * @param options.maximumConsecutiveFailures - The maximum number of consecutive failures\n * allowed before breaking the circuit and pausing further updates.\n * @param options.onBreak - An event handler for when the circuit breaks, useful for capturing\n * metrics about network failures.\n * @param options.onDegraded - An event handler for when the circuit remains closed, but requests\n * are failing or resolving too slowly (i.e. resolving more slowly than the `degradedThreshold).\n * @param options.circuitBreakDuration - The amount of time to wait when the circuit breaks\n * from too many consecutive failures.\n */\n constructor({\n degradedThreshold = DEFAULT_DEGRADED_THRESHOLD,\n retries = DEFAULT_TOKEN_PRICE_RETRIES,\n maximumConsecutiveFailures = DEFAULT_TOKEN_PRICE_MAX_CONSECUTIVE_FAILURES,\n onBreak,\n onDegraded,\n circuitBreakDuration = 30 * 60 * 1000,\n }: {\n degradedThreshold?: number;\n retries?: number;\n maximumConsecutiveFailures?: number;\n onBreak?: () => void;\n onDegraded?: () => void;\n circuitBreakDuration?: number;\n } = {}) {\n // Construct a policy that will retry each update, and halt further updates\n // for a certain period after too many consecutive failures.\n const retryPolicy = retry(handleAll, {\n maxAttempts: retries,\n backoff: new ExponentialBackoff(),\n });\n const circuitBreakerPolicy = circuitBreaker(handleAll, {\n halfOpenAfter: circuitBreakDuration,\n breaker: new ConsecutiveBreaker(maximumConsecutiveFailures),\n });\n if (onBreak) {\n circuitBreakerPolicy.onBreak(onBreak);\n }\n if (onDegraded) {\n retryPolicy.onGiveUp(() => {\n if (circuitBreakerPolicy.state === CircuitState.Closed) {\n onDegraded();\n }\n });\n retryPolicy.onSuccess(({ duration }) => {\n if (\n circuitBreakerPolicy.state === CircuitState.Closed &&\n duration > degradedThreshold\n ) {\n onDegraded();\n }\n });\n }\n this.#tokenPricePolicy = wrap(retryPolicy, circuitBreakerPolicy);\n }\n\n /**\n * Retrieves prices in the given currency for the tokens identified by the\n * given addresses which are expected to live on the given chain.\n *\n * @param args - The arguments to function.\n * @param args.chainId - An EIP-155 chain ID.\n * @param args.tokenAddresses - Addresses for tokens that live on the chain.\n * @param args.currency - The desired currency of the token prices.\n * @returns The prices for the requested tokens.\n */\n async fetchTokenPrices({\n chainId,\n tokenAddresses,\n currency,\n }: {\n chainId: SupportedChainId;\n tokenAddresses: Hex[];\n currency: SupportedCurrency;\n }): Promise<Partial<TokenPricesByTokenAddress<Hex, SupportedCurrency>>> {\n const chainIdAsNumber = hexToNumber(chainId);\n\n const url = new URL(`${BASE_URL}/chains/${chainIdAsNumber}/spot-prices`);\n url.searchParams.append('tokenAddresses', tokenAddresses.join(','));\n url.searchParams.append('vsCurrency', currency);\n\n const pricesByCurrencyByTokenAddress: SpotPricesEndpointData<\n Lowercase<Hex>,\n Lowercase<SupportedCurrency>\n > = await this.#tokenPricePolicy.execute(() => handleFetch(url));\n\n return tokenAddresses.reduce(\n (\n obj: Partial<TokenPricesByTokenAddress<Hex, SupportedCurrency>>,\n tokenAddress,\n ) => {\n // The Price API lowercases both currency and token addresses, so we have\n // to keep track of them and make sure we return the original versions.\n const lowercasedTokenAddress =\n tokenAddress.toLowerCase() as Lowercase<Hex>;\n const lowercasedCurrency =\n currency.toLowerCase() as Lowercase<SupportedCurrency>;\n\n const price =\n pricesByCurrencyByTokenAddress[lowercasedTokenAddress]?.[\n lowercasedCurrency\n ];\n\n if (!price) {\n // console error instead of throwing to not interrupt the fetching of other tokens in case just one fails\n console.error(\n `Could not find price for \"${tokenAddress}\" in \"${currency}\"`,\n );\n }\n\n const tokenPrice: TokenPrice<Hex, SupportedCurrency> = {\n tokenAddress,\n value: price,\n currency,\n };\n\n return {\n ...obj,\n ...(tokenPrice.value !== undefined\n ? { [tokenAddress]: tokenPrice }\n : {}),\n };\n },\n {},\n ) as Partial<TokenPricesByTokenAddress<Hex, SupportedCurrency>>;\n }\n\n /**\n * Type guard for whether the API can return token prices for the given chain\n * ID.\n *\n * @param chainId - The chain ID to check.\n * @returns True if the API supports the chain ID, false otherwise.\n */\n validateChainIdSupported(chainId: unknown): chainId is SupportedChainId {\n const supportedChainIds: readonly string[] = SUPPORTED_CHAIN_IDS;\n return typeof chainId === 'string' && supportedChainIds.includes(chainId);\n }\n\n /**\n * Type guard for whether the API can return token prices in the given\n * currency.\n *\n * @param currency - The currency to check. If a string, can be either\n * lowercase or uppercase.\n * @returns True if the API supports the currency, false otherwise.\n */\n validateCurrencySupported(currency: unknown): currency is SupportedCurrency {\n const supportedCurrencies: readonly string[] = SUPPORTED_CURRENCIES;\n return (\n typeof currency === 'string' &&\n supportedCurrencies.includes(currency.toLowerCase())\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/assets-controllers",
3
- "version": "24.0.0",
3
+ "version": "25.0.0",
4
4
  "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -36,17 +36,17 @@
36
36
  "@ethersproject/contracts": "^5.7.0",
37
37
  "@ethersproject/providers": "^5.7.0",
38
38
  "@metamask/abi-utils": "^2.0.2",
39
- "@metamask/approval-controller": "^5.1.1",
40
- "@metamask/base-controller": "^4.0.1",
39
+ "@metamask/approval-controller": "^5.1.2",
40
+ "@metamask/base-controller": "^4.1.1",
41
41
  "@metamask/contract-metadata": "^2.4.0",
42
- "@metamask/controller-utils": "^8.0.1",
42
+ "@metamask/controller-utils": "^8.0.2",
43
43
  "@metamask/eth-query": "^4.0.0",
44
44
  "@metamask/metamask-eth-abis": "3.0.0",
45
- "@metamask/network-controller": "^17.1.0",
46
- "@metamask/polling-controller": "^4.0.0",
47
- "@metamask/preferences-controller": "^6.0.0",
45
+ "@metamask/network-controller": "^17.2.0",
46
+ "@metamask/polling-controller": "^5.0.0",
47
+ "@metamask/preferences-controller": "^7.0.0",
48
48
  "@metamask/rpc-errors": "^6.1.0",
49
- "@metamask/utils": "^8.2.0",
49
+ "@metamask/utils": "^8.3.0",
50
50
  "@types/uuid": "^8.3.0",
51
51
  "async-mutex": "^0.2.6",
52
52
  "cockatiel": "^3.1.2",
@@ -73,9 +73,9 @@
73
73
  "typescript": "~4.8.4"
74
74
  },
75
75
  "peerDependencies": {
76
- "@metamask/approval-controller": "^5.1.1",
77
- "@metamask/network-controller": "^17.1.0",
78
- "@metamask/preferences-controller": "^6.0.0"
76
+ "@metamask/approval-controller": "^5.1.2",
77
+ "@metamask/network-controller": "^17.2.0",
78
+ "@metamask/preferences-controller": "^7.0.0"
79
79
  },
80
80
  "engines": {
81
81
  "node": ">=16.0.0"