@metamask-previews/assets-controllers 19.0.0-preview.eb58a59 → 20.0.0-preview.3fbb6b41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +47 -1
  2. package/dist/AccountTrackerController.d.ts +2 -2
  3. package/dist/AccountTrackerController.d.ts.map +1 -1
  4. package/dist/AccountTrackerController.js +1 -1
  5. package/dist/AccountTrackerController.js.map +1 -1
  6. package/dist/AssetsContractController.d.ts +5 -5
  7. package/dist/AssetsContractController.d.ts.map +1 -1
  8. package/dist/AssetsContractController.js +6 -4
  9. package/dist/AssetsContractController.js.map +1 -1
  10. package/dist/NftController.d.ts +2 -2
  11. package/dist/NftController.d.ts.map +1 -1
  12. package/dist/NftController.js +1 -1
  13. package/dist/NftController.js.map +1 -1
  14. package/dist/TokenBalancesController.d.ts +2 -2
  15. package/dist/TokenBalancesController.d.ts.map +1 -1
  16. package/dist/TokenBalancesController.js +1 -1
  17. package/dist/TokenBalancesController.js.map +1 -1
  18. package/dist/TokenRatesController.d.ts +59 -58
  19. package/dist/TokenRatesController.d.ts.map +1 -1
  20. package/dist/TokenRatesController.js +151 -156
  21. package/dist/TokenRatesController.js.map +1 -1
  22. package/dist/TokensController.d.ts +5 -5
  23. package/dist/TokensController.d.ts.map +1 -1
  24. package/dist/TokensController.js +4 -4
  25. package/dist/TokensController.js.map +1 -1
  26. package/dist/assetsUtil.d.ts +3 -1
  27. package/dist/assetsUtil.d.ts.map +1 -1
  28. package/dist/assetsUtil.js +2 -0
  29. package/dist/assetsUtil.js.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +3 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/token-prices-service/abstract-token-prices-service.d.ts +63 -0
  35. package/dist/token-prices-service/abstract-token-prices-service.d.ts.map +1 -0
  36. package/dist/token-prices-service/abstract-token-prices-service.js +3 -0
  37. package/dist/token-prices-service/abstract-token-prices-service.js.map +1 -0
  38. package/dist/token-prices-service/codefi-v2.d.ts +31 -0
  39. package/dist/token-prices-service/codefi-v2.d.ts.map +1 -0
  40. package/dist/token-prices-service/codefi-v2.js +286 -0
  41. package/dist/token-prices-service/codefi-v2.js.map +1 -0
  42. package/dist/token-prices-service/index.d.ts +3 -0
  43. package/dist/token-prices-service/index.d.ts.map +1 -0
  44. package/dist/token-prices-service/index.js +6 -0
  45. package/dist/token-prices-service/index.js.map +1 -0
  46. package/package.json +11 -11
@@ -1,30 +1,10 @@
1
1
  import type { BaseConfig, BaseState } from '@metamask/base-controller';
2
- import { BaseController } from '@metamask/base-controller';
3
- import type { NetworkState } from '@metamask/network-controller';
2
+ import type { NetworkClientId, NetworkController, NetworkState } from '@metamask/network-controller';
3
+ import { PollingControllerV1 } from '@metamask/polling-controller';
4
4
  import type { PreferencesState } from '@metamask/preferences-controller';
5
5
  import type { Hex } from '@metamask/utils';
6
+ import type { AbstractTokenPricesService } from './token-prices-service/abstract-token-prices-service';
6
7
  import type { TokensState } from './TokensController';
7
- /**
8
- * @type CoinGeckoResponse
9
- *
10
- * CoinGecko API response representation
11
- */
12
- export interface CoinGeckoResponse {
13
- [address: string]: {
14
- [currency: string]: number;
15
- };
16
- }
17
- /**
18
- * @type CoinGeckoPlatform
19
- *
20
- * CoinGecko supported platform API representation
21
- */
22
- export interface CoinGeckoPlatform {
23
- id: string;
24
- chain_identifier: null | number;
25
- name: string;
26
- shortname: string;
27
- }
28
8
  /**
29
9
  * @type Token
30
10
  *
@@ -78,46 +58,54 @@ interface ContractExchangeRates {
78
58
  * @type TokenRatesState
79
59
  *
80
60
  * Token rates controller state
81
- * @property contractExchangeRates - Hash of token contract addresses to exchange rates
82
- * @property supportedChains - Cached chain data
61
+ * @property contractExchangeRates - Hash of token contract addresses to exchange rates (single globally selected chain, will be deprecated soon)
62
+ * @property contractExchangeRatesByChainId - Hash of token contract addresses to exchange rates keyed by chain ID and native currency (ticker)
83
63
  */
84
64
  export interface TokenRatesState extends BaseState {
85
65
  contractExchangeRates: ContractExchangeRates;
66
+ contractExchangeRatesByChainId: Record<Hex, Record<string, ContractExchangeRates>>;
86
67
  }
87
68
  /**
88
69
  * Controller that passively polls on a set interval for token-to-fiat exchange rates
89
70
  * for tokens stored in the TokensController
90
71
  */
91
- export declare class TokenRatesController extends BaseController<TokenRatesConfig, TokenRatesState> {
72
+ export declare class TokenRatesController extends PollingControllerV1<TokenRatesConfig, TokenRatesState> {
92
73
  #private;
93
74
  private handle?;
94
75
  private tokenList;
95
- private supportedChains;
96
- private supportedVsCurrencies;
97
76
  /**
98
77
  * Name of this controller used during composition
99
78
  */
100
79
  name: string;
80
+ private readonly getNetworkClientById;
101
81
  /**
102
82
  * Creates a TokenRatesController instance.
103
83
  *
104
84
  * @param options - The controller options.
85
+ * @param options.interval - The polling interval in ms
86
+ * @param options.threshold - The duration in ms before metadata fetched from CoinGecko is considered stale
87
+ * @param options.getNetworkClientById - Gets the network client with the given id from the NetworkController.
105
88
  * @param options.chainId - The chain ID of the current network.
106
89
  * @param options.ticker - The ticker for the current network.
107
90
  * @param options.selectedAddress - The current selected address.
108
91
  * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.
109
92
  * @param options.onTokensStateChange - Allows subscribing to token controller state changes.
110
93
  * @param options.onNetworkStateChange - Allows subscribing to network state changes.
94
+ * @param options.tokenPricesService - An object in charge of retrieving token prices.
111
95
  * @param config - Initial options used to configure this controller.
112
96
  * @param state - Initial state to set on this controller.
113
97
  */
114
- constructor({ chainId: initialChainId, ticker: initialTicker, selectedAddress: initialSelectedAddress, onPreferencesStateChange, onTokensStateChange, onNetworkStateChange, }: {
98
+ constructor({ interval, threshold, getNetworkClientById, chainId: initialChainId, ticker: initialTicker, selectedAddress: initialSelectedAddress, onPreferencesStateChange, onTokensStateChange, onNetworkStateChange, tokenPricesService, }: {
99
+ interval?: number;
100
+ threshold?: number;
101
+ getNetworkClientById: NetworkController['getNetworkClientById'];
115
102
  chainId: Hex;
116
103
  ticker: string;
117
104
  selectedAddress: string;
118
105
  onPreferencesStateChange: (listener: (preferencesState: PreferencesState) => void) => void;
119
106
  onTokensStateChange: (listener: (tokensState: TokensState) => void) => void;
120
107
  onNetworkStateChange: (listener: (networkState: NetworkState) => void) => void;
108
+ tokenPricesService: AbstractTokenPricesService;
121
109
  }, config?: Partial<TokenRatesConfig>, state?: Partial<TokenRatesState>);
122
110
  /**
123
111
  * Start (or restart) polling.
@@ -128,45 +116,58 @@ export declare class TokenRatesController extends BaseController<TokenRatesConfi
128
116
  */
129
117
  stop(): void;
130
118
  /**
131
- * Fetches a pairs of token address and native currency.
132
- *
133
- * @param chainSlug - Chain string identifier.
134
- * @param vsCurrency - Query according to tokens in tokenList and native currency.
135
- * @returns The exchange rates for the given pairs.
119
+ * Updates exchange rates for all tokens.
136
120
  */
137
- fetchExchangeRate(chainSlug: string, vsCurrency: string): Promise<CoinGeckoResponse>;
121
+ updateExchangeRates(): Promise<void>;
138
122
  /**
139
- * Checks if the current native currency is a supported vs currency to use
140
- * to query for token exchange rates.
123
+ * Updates exchange rates for all tokens.
141
124
  *
142
- * @param nativeCurrency - The native currency of the currently active network.
143
- * @returns A boolean indicating whether it's a supported vsCurrency.
125
+ * @param options - The options to fetch exchange rates.
126
+ * @param options.chainId - The chain ID.
127
+ * @param options.nativeCurrency - The ticker for the chain.
128
+ * @param options.tokenContractAddresses - The addresses for the token contracts.
144
129
  */
145
- private checkIsSupportedVsCurrency;
130
+ updateExchangeRatesByChainId({ chainId, nativeCurrency, tokenContractAddresses, }: {
131
+ chainId: Hex;
132
+ nativeCurrency: string;
133
+ tokenContractAddresses: Hex[];
134
+ }): Promise<void>;
146
135
  /**
147
- * Gets current chain ID slug from cached supported platforms CoinGecko API response.
148
- * If cached supported platforms response is stale, fetches and updates it.
136
+ * Uses the token prices service to retrieve exchange rates for tokens in a
137
+ * particular currency.
149
138
  *
150
- * @returns The CoinGecko slug for the current chain ID.
151
- */
152
- getChainSlug(): Promise<string | null>;
153
- /**
154
- * Updates exchange rates for all tokens.
139
+ * If the price API does not support the given chain ID, returns an empty
140
+ * object.
141
+ *
142
+ * If the price API does not support the given currency, retrieves exchange
143
+ * rates in a known currency instead, then converts those rates using the
144
+ * exchange rate between the known currency and desired currency.
145
+ *
146
+ * @param args - The arguments to this function.
147
+ * @param args.tokenContractAddresses - Contract addresses for tokens.
148
+ * @param args.chainId - The EIP-155 ID of the chain where the tokens live.
149
+ * @param args.nativeCurrency - The native currency in which to request
150
+ * exchange rates.
151
+ * @returns A map from token contract address to its exchange rate in the
152
+ * native currency, or an empty map if no exchange rates can be obtained for
153
+ * the chain ID.
155
154
  */
156
- updateExchangeRates(): Promise<void>;
155
+ fetchAndMapExchangeRates({ tokenContractAddresses, chainId, nativeCurrency, }: {
156
+ tokenContractAddresses: Hex[];
157
+ chainId: Hex;
158
+ nativeCurrency: string;
159
+ }): Promise<ContractExchangeRates>;
157
160
  /**
158
- * Checks if the active network's native currency is supported by the coingecko API.
159
- * If supported, it fetches and maps contractExchange rates to a format to be consumed by the UI.
160
- * If not supported, it fetches contractExchange rates and maps them from token/fallback-currency
161
- * to token/nativeCurrency.
161
+ * Updates token rates for the given networkClientId and contract addresses
162
162
  *
163
- * @param nativeCurrency - The native currency of the currently active network.
164
- * @param slug - The unique slug used to id the chain by the coingecko api
165
- * should be used to query token exchange rates.
166
- * @returns An object with conversion rates for each token
167
- * related to the network's native currency.
163
+ * @param networkClientId - The network client ID used to get a ticker value.
164
+ * @param options - The polling options.
165
+ * @param options.tokenAddresses - The addresses for the token contracts.
166
+ * @returns The controller state.
168
167
  */
169
- fetchAndMapExchangeRates(nativeCurrency: string, slug: string): Promise<ContractExchangeRates>;
168
+ _executePoll(networkClientId: NetworkClientId, options: {
169
+ tokenAddresses: Hex[];
170
+ }): Promise<void>;
170
171
  }
171
172
  export default TokenRatesController;
172
173
  //# sourceMappingURL=TokenRatesController.d.ts.map
@@ -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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"}
@@ -8,104 +8,105 @@ 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 __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
12
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
13
- 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");
14
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
15
- };
16
11
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
17
12
  if (kind === "m") throw new TypeError("Private method is not writable");
18
13
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
19
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");
20
15
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
21
16
  };
22
- var _TokenRatesController_instances, _TokenRatesController_pollState, _TokenRatesController_updateTokenList, _TokenRatesController_stopPoll, _TokenRatesController_poll;
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 _TokenRatesController_instances, _TokenRatesController_pollState, _TokenRatesController_tokenPricesService, _TokenRatesController_updateTokenList, _TokenRatesController_stopPoll, _TokenRatesController_poll, _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency, _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency;
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.TokenRatesController = void 0;
25
- const base_controller_1 = require("@metamask/base-controller");
26
25
  const controller_utils_1 = require("@metamask/controller-utils");
26
+ const polling_controller_1 = require("@metamask/polling-controller");
27
27
  const crypto_compare_1 = require("./crypto-compare");
28
28
  var PollState;
29
29
  (function (PollState) {
30
30
  PollState["Active"] = "Active";
31
31
  PollState["Inactive"] = "Inactive";
32
32
  })(PollState || (PollState = {}));
33
- const CoinGeckoApi = {
34
- BASE_URL: 'https://api.coingecko.com/api/v3',
35
- getTokenPriceURL(chainSlug, query) {
36
- return `${this.BASE_URL}/simple/token_price/${chainSlug}?${query}`;
37
- },
38
- getPlatformsURL() {
39
- return `${this.BASE_URL}/asset_platforms`;
40
- },
41
- getSupportedVsCurrencies() {
42
- return `${this.BASE_URL}/simple/supported_vs_currencies`;
43
- },
44
- };
45
33
  /**
46
- * Finds the chain slug in the data array given a chainId.
34
+ * Uses the CryptoCompare API to fetch the exchange rate between one currency
35
+ * and another, i.e., the multiplier to apply the amount of one currency in
36
+ * order to convert it to another.
47
37
  *
48
- * @param chainId - The current chain ID.
49
- * @param data - A list platforms supported by the CoinGecko API.
50
- * @returns The CoinGecko slug for the given chain ID, or `null` if the slug was not found.
38
+ * @param args - The arguments to this function.
39
+ * @param args.from - The currency to convert from.
40
+ * @param args.to - The currency to convert to.
41
+ * @returns The exchange rate between `fromCurrency` to `toCurrency` if one
42
+ * exists, or null if one does not.
51
43
  */
52
- function findChainSlug(chainId, data) {
53
- var _a;
54
- if (!data) {
55
- return null;
56
- }
57
- const chain = (_a = data.find(({ chain_identifier }) => chain_identifier !== null && (0, controller_utils_1.toHex)(chain_identifier) === chainId)) !== null && _a !== void 0 ? _a : null;
58
- return (chain === null || chain === void 0 ? void 0 : chain.id) || null;
44
+ function getCurrencyConversionRate({ from, to, }) {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ const includeUSDRate = false;
47
+ try {
48
+ const result = yield (0, crypto_compare_1.fetchExchangeRate)(to, from, includeUSDRate);
49
+ return result.conversionRate;
50
+ }
51
+ catch (error) {
52
+ if (error instanceof Error &&
53
+ error.message.includes('market does not exist for this coin pair')) {
54
+ return null;
55
+ }
56
+ throw error;
57
+ }
58
+ });
59
59
  }
60
60
  /**
61
61
  * Controller that passively polls on a set interval for token-to-fiat exchange rates
62
62
  * for tokens stored in the TokensController
63
63
  */
64
- class TokenRatesController extends base_controller_1.BaseController {
64
+ class TokenRatesController extends polling_controller_1.PollingControllerV1 {
65
65
  /**
66
66
  * Creates a TokenRatesController instance.
67
67
  *
68
68
  * @param options - The controller options.
69
+ * @param options.interval - The polling interval in ms
70
+ * @param options.threshold - The duration in ms before metadata fetched from CoinGecko is considered stale
71
+ * @param options.getNetworkClientById - Gets the network client with the given id from the NetworkController.
69
72
  * @param options.chainId - The chain ID of the current network.
70
73
  * @param options.ticker - The ticker for the current network.
71
74
  * @param options.selectedAddress - The current selected address.
72
75
  * @param options.onPreferencesStateChange - Allows subscribing to preference controller state changes.
73
76
  * @param options.onTokensStateChange - Allows subscribing to token controller state changes.
74
77
  * @param options.onNetworkStateChange - Allows subscribing to network state changes.
78
+ * @param options.tokenPricesService - An object in charge of retrieving token prices.
75
79
  * @param config - Initial options used to configure this controller.
76
80
  * @param state - Initial state to set on this controller.
77
81
  */
78
- constructor({ chainId: initialChainId, ticker: initialTicker, selectedAddress: initialSelectedAddress, onPreferencesStateChange, onTokensStateChange, onNetworkStateChange, }, config, state) {
82
+ constructor({ interval = 3 * 60 * 1000, threshold = 6 * 60 * 60 * 1000, getNetworkClientById, chainId: initialChainId, ticker: initialTicker, selectedAddress: initialSelectedAddress, onPreferencesStateChange, onTokensStateChange, onNetworkStateChange, tokenPricesService, }, config, state) {
79
83
  super(config, state);
80
84
  _TokenRatesController_instances.add(this);
81
85
  this.tokenList = [];
82
- this.supportedChains = {
83
- timestamp: 0,
84
- data: null,
85
- };
86
- this.supportedVsCurrencies = {
87
- timestamp: 0,
88
- data: [],
89
- };
90
86
  _TokenRatesController_pollState.set(this, PollState.Inactive);
87
+ _TokenRatesController_tokenPricesService.set(this, void 0);
91
88
  /**
92
89
  * Name of this controller used during composition
93
90
  */
94
91
  this.name = 'TokenRatesController';
95
92
  this.defaultConfig = {
93
+ interval,
94
+ threshold,
96
95
  disabled: false,
97
- interval: 3 * 60 * 1000,
98
96
  nativeCurrency: initialTicker,
99
97
  chainId: initialChainId,
100
98
  selectedAddress: initialSelectedAddress,
101
99
  allTokens: {},
102
100
  allDetectedTokens: {},
103
- threshold: 6 * 60 * 60 * 1000,
104
101
  };
105
102
  this.defaultState = {
106
103
  contractExchangeRates: {},
104
+ contractExchangeRatesByChainId: {},
107
105
  };
108
106
  this.initialize();
107
+ this.setIntervalLength(interval);
108
+ this.getNetworkClientById = getNetworkClientById;
109
+ __classPrivateFieldSet(this, _TokenRatesController_tokenPricesService, tokenPricesService, "f");
109
110
  if (config === null || config === void 0 ? void 0 : config.disabled) {
110
111
  this.configure({ disabled: true }, false, false);
111
112
  }
@@ -161,148 +162,111 @@ class TokenRatesController extends base_controller_1.BaseController {
161
162
  __classPrivateFieldSet(this, _TokenRatesController_pollState, PollState.Inactive, "f");
162
163
  }
163
164
  /**
164
- * Fetches a pairs of token address and native currency.
165
- *
166
- * @param chainSlug - Chain string identifier.
167
- * @param vsCurrency - Query according to tokens in tokenList and native currency.
168
- * @returns The exchange rates for the given pairs.
169
- */
170
- fetchExchangeRate(chainSlug, vsCurrency) {
171
- return __awaiter(this, void 0, void 0, function* () {
172
- const tokenPairs = this.tokenList.map((token) => token.address).join(',');
173
- const query = `contract_addresses=${tokenPairs}&vs_currencies=${vsCurrency.toLowerCase()}`;
174
- return (0, controller_utils_1.handleFetch)(CoinGeckoApi.getTokenPriceURL(chainSlug, query));
175
- });
176
- }
177
- /**
178
- * Checks if the current native currency is a supported vs currency to use
179
- * to query for token exchange rates.
180
- *
181
- * @param nativeCurrency - The native currency of the currently active network.
182
- * @returns A boolean indicating whether it's a supported vsCurrency.
165
+ * Updates exchange rates for all tokens.
183
166
  */
184
- checkIsSupportedVsCurrency(nativeCurrency) {
167
+ updateExchangeRates() {
185
168
  return __awaiter(this, void 0, void 0, function* () {
186
- const { threshold } = this.config;
187
- const { timestamp, data } = this.supportedVsCurrencies;
188
- const now = Date.now();
189
- if (now - timestamp > threshold) {
190
- const currencies = yield (0, controller_utils_1.handleFetch)(CoinGeckoApi.getSupportedVsCurrencies());
191
- this.supportedVsCurrencies = {
192
- data: currencies,
193
- timestamp: Date.now(),
194
- };
195
- return currencies.includes(nativeCurrency.toLowerCase());
169
+ if (this.tokenList.length === 0 || this.disabled) {
170
+ return;
196
171
  }
197
- return data.includes(nativeCurrency.toLowerCase());
172
+ const { chainId, nativeCurrency } = this.config;
173
+ const tokenContractAddresses = this.tokenList.map((token) => token.address);
174
+ yield this.updateExchangeRatesByChainId({
175
+ chainId,
176
+ nativeCurrency,
177
+ tokenContractAddresses,
178
+ });
179
+ this.update({
180
+ contractExchangeRates: this.state.contractExchangeRatesByChainId[chainId][nativeCurrency],
181
+ });
198
182
  });
199
183
  }
200
184
  /**
201
- * Gets current chain ID slug from cached supported platforms CoinGecko API response.
202
- * If cached supported platforms response is stale, fetches and updates it.
185
+ * Updates exchange rates for all tokens.
203
186
  *
204
- * @returns The CoinGecko slug for the current chain ID.
187
+ * @param options - The options to fetch exchange rates.
188
+ * @param options.chainId - The chain ID.
189
+ * @param options.nativeCurrency - The ticker for the chain.
190
+ * @param options.tokenContractAddresses - The addresses for the token contracts.
205
191
  */
206
- getChainSlug() {
192
+ updateExchangeRatesByChainId({ chainId, nativeCurrency, tokenContractAddresses, }) {
193
+ var _a;
207
194
  return __awaiter(this, void 0, void 0, function* () {
208
- const { threshold, chainId } = this.config;
209
- const { data, timestamp } = this.supportedChains;
210
- const now = Date.now();
211
- if (now - timestamp > threshold) {
212
- const platforms = yield (0, controller_utils_1.handleFetch)(CoinGeckoApi.getPlatformsURL());
213
- this.supportedChains = {
214
- data: platforms,
215
- timestamp: Date.now(),
216
- };
217
- return findChainSlug(chainId, platforms);
195
+ if (tokenContractAddresses.length === 0 || this.disabled) {
196
+ return;
218
197
  }
219
- return findChainSlug(chainId, data);
198
+ const newContractExchangeRates = yield this.fetchAndMapExchangeRates({
199
+ tokenContractAddresses,
200
+ chainId,
201
+ nativeCurrency,
202
+ });
203
+ const existingContractExchangeRatesForChainId = (_a = this.state.contractExchangeRatesByChainId[chainId]) !== null && _a !== void 0 ? _a : {};
204
+ this.update({
205
+ contractExchangeRatesByChainId: Object.assign(Object.assign({}, this.state.contractExchangeRatesByChainId), { [chainId]: Object.assign(Object.assign({}, existingContractExchangeRatesForChainId), { [nativeCurrency]: Object.assign(Object.assign({}, existingContractExchangeRatesForChainId[nativeCurrency]), newContractExchangeRates) }) }),
206
+ });
220
207
  });
221
208
  }
222
209
  /**
223
- * Updates exchange rates for all tokens.
210
+ * Uses the token prices service to retrieve exchange rates for tokens in a
211
+ * particular currency.
212
+ *
213
+ * If the price API does not support the given chain ID, returns an empty
214
+ * object.
215
+ *
216
+ * If the price API does not support the given currency, retrieves exchange
217
+ * rates in a known currency instead, then converts those rates using the
218
+ * exchange rate between the known currency and desired currency.
219
+ *
220
+ * @param args - The arguments to this function.
221
+ * @param args.tokenContractAddresses - Contract addresses for tokens.
222
+ * @param args.chainId - The EIP-155 ID of the chain where the tokens live.
223
+ * @param args.nativeCurrency - The native currency in which to request
224
+ * exchange rates.
225
+ * @returns A map from token contract address to its exchange rate in the
226
+ * native currency, or an empty map if no exchange rates can be obtained for
227
+ * the chain ID.
224
228
  */
225
- updateExchangeRates() {
229
+ fetchAndMapExchangeRates({ tokenContractAddresses, chainId, nativeCurrency, }) {
226
230
  return __awaiter(this, void 0, void 0, function* () {
227
- if (this.tokenList.length === 0 || this.disabled) {
228
- return;
231
+ if (!__classPrivateFieldGet(this, _TokenRatesController_tokenPricesService, "f").validateChainIdSupported(chainId)) {
232
+ return tokenContractAddresses.reduce((obj, tokenContractAddress) => {
233
+ return Object.assign(Object.assign({}, obj), { [tokenContractAddress]: undefined });
234
+ }, {});
229
235
  }
230
- const slug = yield this.getChainSlug();
231
- let newContractExchangeRates = {};
232
- if (!slug) {
233
- this.tokenList.forEach((token) => {
234
- const address = (0, controller_utils_1.toChecksumHexAddress)(token.address);
235
- newContractExchangeRates[address] = undefined;
236
+ if (__classPrivateFieldGet(this, _TokenRatesController_tokenPricesService, "f").validateCurrencySupported(nativeCurrency)) {
237
+ return yield __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency).call(this, {
238
+ tokenContractAddresses,
239
+ chainId,
240
+ nativeCurrency,
236
241
  });
237
242
  }
238
- else {
239
- const { nativeCurrency } = this.config;
240
- newContractExchangeRates = yield this.fetchAndMapExchangeRates(nativeCurrency, slug);
241
- }
242
- this.update({ contractExchangeRates: newContractExchangeRates });
243
+ return yield __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency).call(this, {
244
+ tokenContractAddresses,
245
+ nativeCurrency,
246
+ });
243
247
  });
244
248
  }
245
249
  /**
246
- * Checks if the active network's native currency is supported by the coingecko API.
247
- * If supported, it fetches and maps contractExchange rates to a format to be consumed by the UI.
248
- * If not supported, it fetches contractExchange rates and maps them from token/fallback-currency
249
- * to token/nativeCurrency.
250
+ * Updates token rates for the given networkClientId and contract addresses
250
251
  *
251
- * @param nativeCurrency - The native currency of the currently active network.
252
- * @param slug - The unique slug used to id the chain by the coingecko api
253
- * should be used to query token exchange rates.
254
- * @returns An object with conversion rates for each token
255
- * related to the network's native currency.
252
+ * @param networkClientId - The network client ID used to get a ticker value.
253
+ * @param options - The polling options.
254
+ * @param options.tokenAddresses - The addresses for the token contracts.
255
+ * @returns The controller state.
256
256
  */
257
- fetchAndMapExchangeRates(nativeCurrency, slug) {
257
+ _executePoll(networkClientId, options) {
258
258
  return __awaiter(this, void 0, void 0, function* () {
259
- const contractExchangeRates = {};
260
- // check if native currency is supported as a vs_currency by the API
261
- const nativeCurrencySupported = yield this.checkIsSupportedVsCurrency(nativeCurrency);
262
- if (nativeCurrencySupported) {
263
- // If it is we can do a simple fetch against the CoinGecko API
264
- const prices = yield this.fetchExchangeRate(slug, nativeCurrency);
265
- this.tokenList.forEach((token) => {
266
- const price = prices[token.address.toLowerCase()];
267
- contractExchangeRates[(0, controller_utils_1.toChecksumHexAddress)(token.address)] = price
268
- ? price[nativeCurrency.toLowerCase()]
269
- : 0;
270
- });
271
- }
272
- else {
273
- // if native currency is not supported we need to use a fallback vsCurrency, get the exchange rates
274
- // in token/fallback-currency format and convert them to expected token/nativeCurrency format.
275
- let tokenExchangeRates;
276
- let vsCurrencyToNativeCurrencyConversionRate = 0;
277
- try {
278
- [
279
- tokenExchangeRates,
280
- { conversionRate: vsCurrencyToNativeCurrencyConversionRate },
281
- ] = yield Promise.all([
282
- this.fetchExchangeRate(slug, controller_utils_1.FALL_BACK_VS_CURRENCY),
283
- (0, crypto_compare_1.fetchExchangeRate)(nativeCurrency, controller_utils_1.FALL_BACK_VS_CURRENCY, false),
284
- ]);
285
- }
286
- catch (error) {
287
- if (error instanceof Error &&
288
- error.message.includes('market does not exist for this coin pair')) {
289
- return {};
290
- }
291
- throw error;
292
- }
293
- for (const [tokenAddress, conversion] of Object.entries(tokenExchangeRates)) {
294
- const tokenToVsCurrencyConversionRate = conversion[controller_utils_1.FALL_BACK_VS_CURRENCY.toLowerCase()];
295
- contractExchangeRates[(0, controller_utils_1.toChecksumHexAddress)(tokenAddress)] =
296
- tokenToVsCurrencyConversionRate *
297
- vsCurrencyToNativeCurrencyConversionRate;
298
- }
299
- }
300
- return contractExchangeRates;
259
+ const networkClient = this.getNetworkClientById(networkClientId);
260
+ yield this.updateExchangeRatesByChainId({
261
+ chainId: networkClient.configuration.chainId,
262
+ nativeCurrency: networkClient.configuration.ticker,
263
+ tokenContractAddresses: options.tokenAddresses,
264
+ });
301
265
  });
302
266
  }
303
267
  }
304
268
  exports.TokenRatesController = TokenRatesController;
305
- _TokenRatesController_pollState = new WeakMap(), _TokenRatesController_instances = new WeakSet(), _TokenRatesController_updateTokenList = function _TokenRatesController_updateTokenList() {
269
+ _TokenRatesController_pollState = new WeakMap(), _TokenRatesController_tokenPricesService = new WeakMap(), _TokenRatesController_instances = new WeakSet(), _TokenRatesController_updateTokenList = function _TokenRatesController_updateTokenList() {
306
270
  var _a, _b;
307
271
  const { allTokens, allDetectedTokens } = this.config;
308
272
  const tokens = ((_a = allTokens[this.config.chainId]) === null || _a === void 0 ? void 0 : _a[this.config.selectedAddress]) || [];
@@ -322,6 +286,37 @@ _TokenRatesController_pollState = new WeakMap(), _TokenRatesController_instances
322
286
  __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_poll).call(this);
323
287
  }, this.config.interval);
324
288
  });
289
+ }, _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency = function _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency({ tokenContractAddresses, chainId, nativeCurrency, }) {
290
+ return __awaiter(this, void 0, void 0, function* () {
291
+ const tokenPricesByTokenContractAddress = yield __classPrivateFieldGet(this, _TokenRatesController_tokenPricesService, "f").fetchTokenPrices({
292
+ tokenContractAddresses,
293
+ chainId,
294
+ currency: nativeCurrency,
295
+ });
296
+ return Object.entries(tokenPricesByTokenContractAddress).reduce((obj, [tokenContractAddress, tokenPrice]) => {
297
+ return Object.assign(Object.assign({}, obj), { [(0, controller_utils_1.toChecksumHexAddress)(tokenContractAddress)]: tokenPrice.value });
298
+ }, {});
299
+ });
300
+ }, _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency = function _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency({ tokenContractAddresses, nativeCurrency, }) {
301
+ return __awaiter(this, void 0, void 0, function* () {
302
+ const [tokenPricesByTokenContractAddress, fallbackCurrencyToNativeCurrencyConversionRate,] = yield Promise.all([
303
+ __classPrivateFieldGet(this, _TokenRatesController_tokenPricesService, "f").fetchTokenPrices({
304
+ tokenContractAddresses,
305
+ currency: controller_utils_1.FALL_BACK_VS_CURRENCY,
306
+ chainId: this.config.chainId,
307
+ }),
308
+ getCurrencyConversionRate({
309
+ from: controller_utils_1.FALL_BACK_VS_CURRENCY,
310
+ to: nativeCurrency,
311
+ }),
312
+ ]);
313
+ if (fallbackCurrencyToNativeCurrencyConversionRate === null) {
314
+ return {};
315
+ }
316
+ return Object.entries(tokenPricesByTokenContractAddress).reduce((obj, [tokenContractAddress, tokenPrice]) => {
317
+ return Object.assign(Object.assign({}, obj), { [(0, controller_utils_1.toChecksumHexAddress)(tokenContractAddress)]: tokenPrice.value * fallbackCurrencyToNativeCurrencyConversionRate });
318
+ }, {});
319
+ });
325
320
  };
326
321
  exports.default = TokenRatesController;
327
322
  //# sourceMappingURL=TokenRatesController.js.map