@metamask/assets-controllers 41.0.0 → 43.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -1
- package/dist/AccountTrackerController.cjs +30 -10
- package/dist/AccountTrackerController.cjs.map +1 -1
- package/dist/AccountTrackerController.d.cts +14 -9
- package/dist/AccountTrackerController.d.cts.map +1 -1
- package/dist/AccountTrackerController.d.mts +14 -9
- package/dist/AccountTrackerController.d.mts.map +1 -1
- package/dist/AccountTrackerController.mjs +30 -10
- package/dist/AccountTrackerController.mjs.map +1 -1
- package/dist/AssetsContractController.cjs +61 -1
- package/dist/AssetsContractController.cjs.map +1 -1
- package/dist/AssetsContractController.d.cts +13 -0
- package/dist/AssetsContractController.d.cts.map +1 -1
- package/dist/AssetsContractController.d.mts +13 -0
- package/dist/AssetsContractController.d.mts.map +1 -1
- package/dist/AssetsContractController.mjs +61 -1
- package/dist/AssetsContractController.mjs.map +1 -1
- package/dist/CurrencyRateController.d.cts +4 -4
- package/dist/CurrencyRateController.d.mts +4 -4
- package/dist/NftController.cjs +8 -0
- package/dist/NftController.cjs.map +1 -1
- package/dist/NftController.d.cts +4 -0
- package/dist/NftController.d.cts.map +1 -1
- package/dist/NftController.d.mts +4 -0
- package/dist/NftController.d.mts.map +1 -1
- package/dist/NftController.mjs +8 -0
- package/dist/NftController.mjs.map +1 -1
- package/dist/TokenBalancesController.cjs +8 -0
- package/dist/TokenBalancesController.cjs.map +1 -1
- package/dist/TokenBalancesController.d.cts +4 -0
- package/dist/TokenBalancesController.d.cts.map +1 -1
- package/dist/TokenBalancesController.d.mts +4 -0
- package/dist/TokenBalancesController.d.mts.map +1 -1
- package/dist/TokenBalancesController.mjs +8 -0
- package/dist/TokenBalancesController.mjs.map +1 -1
- package/dist/TokenDetectionController.cjs +196 -129
- package/dist/TokenDetectionController.cjs.map +1 -1
- package/dist/TokenDetectionController.d.cts +23 -12
- package/dist/TokenDetectionController.d.cts.map +1 -1
- package/dist/TokenDetectionController.d.mts +23 -12
- package/dist/TokenDetectionController.d.mts.map +1 -1
- package/dist/TokenDetectionController.mjs +195 -129
- package/dist/TokenDetectionController.mjs.map +1 -1
- package/dist/TokenListController.cjs +60 -53
- package/dist/TokenListController.cjs.map +1 -1
- package/dist/TokenListController.d.cts +25 -14
- package/dist/TokenListController.d.cts.map +1 -1
- package/dist/TokenListController.d.mts +25 -14
- package/dist/TokenListController.d.mts.map +1 -1
- package/dist/TokenListController.mjs +60 -53
- package/dist/TokenListController.mjs.map +1 -1
- package/dist/TokenRatesController.cjs +43 -13
- package/dist/TokenRatesController.cjs.map +1 -1
- package/dist/TokenRatesController.d.cts +12 -8
- package/dist/TokenRatesController.d.cts.map +1 -1
- package/dist/TokenRatesController.d.mts +12 -8
- package/dist/TokenRatesController.d.mts.map +1 -1
- package/dist/TokenRatesController.mjs +43 -13
- package/dist/TokenRatesController.mjs.map +1 -1
- package/dist/TokensController.cjs +15 -4
- package/dist/TokensController.cjs.map +1 -1
- package/dist/TokensController.d.cts +4 -0
- package/dist/TokensController.d.cts.map +1 -1
- package/dist/TokensController.d.mts +4 -0
- package/dist/TokensController.d.mts.map +1 -1
- package/dist/TokensController.mjs +15 -4
- package/dist/TokensController.mjs.map +1 -1
- package/dist/assetsUtil.cjs +13 -1
- package/dist/assetsUtil.cjs.map +1 -1
- package/dist/assetsUtil.d.cts +7 -0
- package/dist/assetsUtil.d.cts.map +1 -1
- package/dist/assetsUtil.d.mts +7 -0
- package/dist/assetsUtil.d.mts.map +1 -1
- package/dist/assetsUtil.mjs +12 -0
- package/dist/assetsUtil.mjs.map +1 -1
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.cjs +18 -0
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.cjs.map +1 -1
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.d.cts.map +1 -1
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.d.mts.map +1 -1
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.mjs +18 -0
- package/dist/multi-chain-accounts-service/mocks/mock-get-balances.mjs.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs +7 -2
- package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts +3 -2
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts +3 -2
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs +7 -2
- package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs.map +1 -1
- package/package.json +9 -9
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedControllerMessenger } from "@metamask/base-controller";
|
|
2
|
-
import type {
|
|
2
|
+
import type { NetworkControllerStateChangeEvent, NetworkState, NetworkControllerGetNetworkClientByIdAction } from "@metamask/network-controller";
|
|
3
3
|
import type { Hex } from "@metamask/utils";
|
|
4
4
|
declare const name = "TokenListController";
|
|
5
5
|
export type TokenListToken = {
|
|
@@ -34,17 +34,17 @@ export type TokenListControllerMessenger = RestrictedControllerMessenger<typeof
|
|
|
34
34
|
export declare const getDefaultTokenListState: () => TokenListState;
|
|
35
35
|
/** The input to start polling for the {@link TokenListController} */
|
|
36
36
|
type TokenListPollingInput = {
|
|
37
|
-
|
|
37
|
+
chainId: Hex;
|
|
38
38
|
};
|
|
39
39
|
declare const TokenListController_base: (abstract new (...args: any[]) => {
|
|
40
|
-
readonly "__#
|
|
41
|
-
"__#
|
|
40
|
+
readonly "__#787887@#intervalIds": Record<string, NodeJS.Timeout>;
|
|
41
|
+
"__#787887@#intervalLength": number | undefined;
|
|
42
42
|
setIntervalLength(intervalLength: number): void;
|
|
43
43
|
getIntervalLength(): number | undefined;
|
|
44
44
|
_startPolling(input: TokenListPollingInput): void;
|
|
45
45
|
_stopPollingByPollingTokenSetId(key: string): void;
|
|
46
|
-
readonly "__#
|
|
47
|
-
"__#
|
|
46
|
+
readonly "__#787879@#pollingTokenSets": Map<string, Set<string>>;
|
|
47
|
+
"__#787879@#callbacks": Map<string, Set<(input: TokenListPollingInput) => void>>;
|
|
48
48
|
_executePoll(input: TokenListPollingInput): Promise<void>;
|
|
49
49
|
startPolling(input: TokenListPollingInput): string;
|
|
50
50
|
stopAllPolling(): void;
|
|
@@ -85,38 +85,49 @@ export declare class TokenListController extends TokenListController_base<typeof
|
|
|
85
85
|
});
|
|
86
86
|
/**
|
|
87
87
|
* Start polling for the token list.
|
|
88
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
89
|
+
* Consider using the new polling approach instead
|
|
88
90
|
*/
|
|
89
91
|
start(): Promise<void>;
|
|
90
92
|
/**
|
|
91
93
|
* Restart polling for the token list.
|
|
94
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
95
|
+
* Consider using the new polling approach instead
|
|
92
96
|
*/
|
|
93
97
|
restart(): Promise<void>;
|
|
94
98
|
/**
|
|
95
99
|
* Stop polling for the token list.
|
|
100
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
101
|
+
* Consider using the new polling approach instead
|
|
96
102
|
*/
|
|
97
103
|
stop(): void;
|
|
98
104
|
/**
|
|
99
|
-
* Prepare to discard this controller.
|
|
100
|
-
*
|
|
101
105
|
* This stops any active polling.
|
|
106
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
107
|
+
* Consider using the new polling approach instead
|
|
102
108
|
*/
|
|
103
109
|
destroy(): void;
|
|
110
|
+
/**
|
|
111
|
+
* This stops any active polling intervals.
|
|
112
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
113
|
+
* Consider using the new polling approach instead
|
|
114
|
+
*/
|
|
104
115
|
private stopPolling;
|
|
105
116
|
/**
|
|
106
|
-
*
|
|
117
|
+
* This starts a new polling loop for any given chain. Under the hood it is deduping polls
|
|
107
118
|
*
|
|
108
119
|
* @private
|
|
109
120
|
* @param input - The input for the poll.
|
|
110
|
-
* @param input.
|
|
121
|
+
* @param input.chainId - The chainId of the chain to trigger the fetch.
|
|
111
122
|
* @returns A promise that resolves when this operation completes.
|
|
112
123
|
*/
|
|
113
|
-
_executePoll({
|
|
124
|
+
_executePoll({ chainId }: TokenListPollingInput): Promise<void>;
|
|
114
125
|
/**
|
|
115
|
-
* Fetching token list from the Token Service API.
|
|
126
|
+
* Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)
|
|
116
127
|
*
|
|
117
|
-
* @param
|
|
128
|
+
* @param chainId - The chainId of the current chain triggering the fetch.
|
|
118
129
|
*/
|
|
119
|
-
fetchTokenList(
|
|
130
|
+
fetchTokenList(chainId: Hex): Promise<void>;
|
|
120
131
|
/**
|
|
121
132
|
* Clearing tokenList and tokensChainsCache explicitly.
|
|
122
133
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenListController.d.mts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,6BAA6B,EAC9B,kCAAkC;AAEnC,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"TokenListController.d.mts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
3
3
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
|
-
var _TokenListController_instances, _TokenListController_onNetworkControllerStateChange,
|
|
6
|
+
var _TokenListController_instances, _TokenListController_onNetworkControllerStateChange, _TokenListController_startDeprecatedPolling, _TokenListController_fetchFromCache;
|
|
7
7
|
import { safelyExecute } from "@metamask/controller-utils";
|
|
8
8
|
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
|
9
9
|
import { Mutex } from "async-mutex";
|
|
@@ -50,6 +50,7 @@ export class TokenListController extends StaticIntervalPollingController() {
|
|
|
50
50
|
_TokenListController_instances.add(this);
|
|
51
51
|
this.mutex = new Mutex();
|
|
52
52
|
this.intervalDelay = interval;
|
|
53
|
+
this.setIntervalLength(interval);
|
|
53
54
|
this.cacheRefreshThreshold = cacheRefreshThreshold;
|
|
54
55
|
this.chainId = chainId;
|
|
55
56
|
this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);
|
|
@@ -70,112 +71,116 @@ export class TokenListController extends StaticIntervalPollingController() {
|
|
|
70
71
|
});
|
|
71
72
|
}
|
|
72
73
|
}
|
|
74
|
+
// Eventually we want to remove start/restart/stop controls in favor of new _executePoll API
|
|
75
|
+
// Maintaining these functions for now until we can safely deprecate them for backwards compatibility
|
|
73
76
|
/**
|
|
74
77
|
* Start polling for the token list.
|
|
78
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
79
|
+
* Consider using the new polling approach instead
|
|
75
80
|
*/
|
|
76
81
|
async start() {
|
|
77
82
|
if (!isTokenListSupportedForNetwork(this.chainId)) {
|
|
78
83
|
return;
|
|
79
84
|
}
|
|
80
|
-
await __classPrivateFieldGet(this, _TokenListController_instances, "m",
|
|
85
|
+
await __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_startDeprecatedPolling).call(this);
|
|
81
86
|
}
|
|
82
87
|
/**
|
|
83
88
|
* Restart polling for the token list.
|
|
89
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
90
|
+
* Consider using the new polling approach instead
|
|
84
91
|
*/
|
|
85
92
|
async restart() {
|
|
86
93
|
this.stopPolling();
|
|
87
|
-
await __classPrivateFieldGet(this, _TokenListController_instances, "m",
|
|
94
|
+
await __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_startDeprecatedPolling).call(this);
|
|
88
95
|
}
|
|
89
96
|
/**
|
|
90
97
|
* Stop polling for the token list.
|
|
98
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
99
|
+
* Consider using the new polling approach instead
|
|
91
100
|
*/
|
|
92
101
|
stop() {
|
|
93
102
|
this.stopPolling();
|
|
94
103
|
}
|
|
95
104
|
/**
|
|
96
|
-
* Prepare to discard this controller.
|
|
97
|
-
*
|
|
98
105
|
* This stops any active polling.
|
|
106
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
107
|
+
* Consider using the new polling approach instead
|
|
99
108
|
*/
|
|
100
109
|
destroy() {
|
|
101
110
|
super.destroy();
|
|
102
111
|
this.stopPolling();
|
|
103
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* This stops any active polling intervals.
|
|
115
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
116
|
+
* Consider using the new polling approach instead
|
|
117
|
+
*/
|
|
104
118
|
stopPolling() {
|
|
105
119
|
if (this.intervalId) {
|
|
106
120
|
clearInterval(this.intervalId);
|
|
107
121
|
}
|
|
108
122
|
}
|
|
109
123
|
/**
|
|
110
|
-
*
|
|
124
|
+
* This starts a new polling loop for any given chain. Under the hood it is deduping polls
|
|
111
125
|
*
|
|
112
126
|
* @private
|
|
113
127
|
* @param input - The input for the poll.
|
|
114
|
-
* @param input.
|
|
128
|
+
* @param input.chainId - The chainId of the chain to trigger the fetch.
|
|
115
129
|
* @returns A promise that resolves when this operation completes.
|
|
116
130
|
*/
|
|
117
|
-
async _executePoll({
|
|
118
|
-
return this.fetchTokenList(
|
|
131
|
+
async _executePoll({ chainId }) {
|
|
132
|
+
return this.fetchTokenList(chainId);
|
|
119
133
|
}
|
|
120
134
|
/**
|
|
121
|
-
* Fetching token list from the Token Service API.
|
|
135
|
+
* Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)
|
|
122
136
|
*
|
|
123
|
-
* @param
|
|
137
|
+
* @param chainId - The chainId of the current chain triggering the fetch.
|
|
124
138
|
*/
|
|
125
|
-
async fetchTokenList(
|
|
139
|
+
async fetchTokenList(chainId) {
|
|
126
140
|
const releaseLock = await this.mutex.acquire();
|
|
127
|
-
let networkClient;
|
|
128
|
-
if (networkClientId) {
|
|
129
|
-
networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientId);
|
|
130
|
-
}
|
|
131
|
-
const chainId = networkClient?.configuration.chainId ?? this.chainId;
|
|
132
141
|
try {
|
|
133
142
|
const { tokensChainsCache } = this.state;
|
|
134
143
|
let tokenList = {};
|
|
144
|
+
// Attempt to fetch cached tokens
|
|
135
145
|
const cachedTokens = await safelyExecute(() => __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_fetchFromCache).call(this, chainId));
|
|
136
146
|
if (cachedTokens) {
|
|
137
147
|
// Use non-expired cached tokens
|
|
138
148
|
tokenList = { ...cachedTokens };
|
|
139
149
|
}
|
|
140
150
|
else {
|
|
141
|
-
// Fetch fresh token list
|
|
151
|
+
// Fetch fresh token list from the API
|
|
142
152
|
const tokensFromAPI = await safelyExecute(() => fetchTokenListByChainId(chainId, this.abortController.signal));
|
|
143
|
-
if (
|
|
144
|
-
//
|
|
145
|
-
tokenList = {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
...
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
if (tokensFromAPI) {
|
|
154
|
+
// Format tokens from API (HTTP) and update tokenList
|
|
155
|
+
tokenList = {};
|
|
156
|
+
for (const token of tokensFromAPI) {
|
|
157
|
+
tokenList[token.address] = {
|
|
158
|
+
...token,
|
|
159
|
+
aggregators: formatAggregatorNames(token.aggregators),
|
|
160
|
+
iconUrl: formatIconUrlWithProxy({
|
|
161
|
+
chainId,
|
|
162
|
+
tokenAddress: token.address,
|
|
163
|
+
}),
|
|
151
164
|
};
|
|
152
|
-
}
|
|
153
|
-
return;
|
|
165
|
+
}
|
|
154
166
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
aggregators: formatAggregatorNames(token.aggregators),
|
|
159
|
-
iconUrl: formatIconUrlWithProxy({
|
|
160
|
-
chainId,
|
|
161
|
-
tokenAddress: token.address,
|
|
162
|
-
}),
|
|
163
|
-
};
|
|
164
|
-
tokenList[token.address] = formattedToken;
|
|
167
|
+
else {
|
|
168
|
+
// Fallback to expired cached tokens
|
|
169
|
+
tokenList = { ...(tokensChainsCache[chainId]?.data || {}) };
|
|
165
170
|
}
|
|
166
171
|
}
|
|
167
|
-
|
|
168
|
-
...tokensChainsCache,
|
|
169
|
-
[chainId]: {
|
|
170
|
-
timestamp: Date.now(),
|
|
171
|
-
data: tokenList,
|
|
172
|
-
},
|
|
173
|
-
};
|
|
172
|
+
// Update the state with a single update for both tokenList and tokenChainsCache
|
|
174
173
|
this.update(() => {
|
|
175
174
|
return {
|
|
176
175
|
...this.state,
|
|
177
|
-
tokenList,
|
|
178
|
-
tokensChainsCache:
|
|
176
|
+
tokenList: this.chainId === chainId ? tokenList : this.state.tokenList,
|
|
177
|
+
tokensChainsCache: {
|
|
178
|
+
...tokensChainsCache,
|
|
179
|
+
[chainId]: {
|
|
180
|
+
timestamp: Date.now(),
|
|
181
|
+
data: tokenList,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
179
184
|
};
|
|
180
185
|
});
|
|
181
186
|
}
|
|
@@ -234,19 +239,21 @@ async function _TokenListController_onNetworkControllerStateChange(networkContro
|
|
|
234
239
|
tokenList: this.state.tokensChainsCache[this.chainId]?.data || {},
|
|
235
240
|
};
|
|
236
241
|
});
|
|
237
|
-
await this.restart();
|
|
238
242
|
}
|
|
239
243
|
}
|
|
240
|
-
},
|
|
244
|
+
}, _TokenListController_startDeprecatedPolling =
|
|
241
245
|
/**
|
|
242
|
-
* Starts a new polling interval
|
|
246
|
+
* Starts a new polling interval for a given chainId (this should be deprecated in favor of _executePoll)
|
|
247
|
+
* @deprecated This method is deprecated and will be removed in the future.
|
|
248
|
+
* Consider using the new polling approach instead
|
|
243
249
|
*/
|
|
244
|
-
async function
|
|
245
|
-
|
|
250
|
+
async function _TokenListController_startDeprecatedPolling() {
|
|
251
|
+
// renaming this to avoid collision with base class
|
|
252
|
+
await safelyExecute(() => this.fetchTokenList(this.chainId));
|
|
246
253
|
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
247
254
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
248
255
|
this.intervalId = setInterval(async () => {
|
|
249
|
-
await safelyExecute(() => this.fetchTokenList());
|
|
256
|
+
await safelyExecute(() => this.fetchTokenList(this.chainId));
|
|
250
257
|
}, this.intervalDelay);
|
|
251
258
|
}, _TokenListController_fetchFromCache =
|
|
252
259
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenListController.mjs","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenListByChainId } from './token-service';\n\nconst DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\nexport type TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokenList: TokenListMap;\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = ControllerStateChangeEvent<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerEvents = TokenListStateChange;\n\nexport type GetTokenListState = ControllerGetStateAction<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerActions = GetTokenListState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype AllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type TokenListControllerMessenger = RestrictedControllerMessenger<\n typeof name,\n TokenListControllerActions | AllowedActions,\n TokenListControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\nconst metadata = {\n tokenList: { persist: true, anonymous: true },\n tokensChainsCache: { persist: true, anonymous: true },\n preventPollingOnNetworkRestart: { persist: true, anonymous: true },\n};\n\nexport const getDefaultTokenListState = (): TokenListState => {\n return {\n tokenList: {},\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n };\n};\n\n/** The input to start polling for the {@link TokenListController} */\ntype TokenListPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends StaticIntervalPollingController<TokenListPollingInput>()<\n typeof name,\n TokenListState,\n TokenListControllerMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted controller messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListControllerMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...getDefaultTokenListState(), ...state },\n });\n this.intervalDelay = interval;\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(networkControllerState: NetworkState) {\n const selectedNetworkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkControllerState.selectedNetworkClientId,\n );\n const { chainId } = selectedNetworkClient.configuration;\n\n if (this.chainId !== chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n } else {\n // Ensure tokenList is referencing data from correct network\n this.update(() => {\n return {\n ...this.state,\n tokenList: this.state.tokensChainsCache[this.chainId]?.data || {},\n };\n });\n await this.restart();\n }\n }\n }\n\n /**\n * Start polling for the token list.\n */\n async start() {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.#startPolling();\n }\n\n /**\n * Restart polling for the token list.\n */\n async restart() {\n this.stopPolling();\n await this.#startPolling();\n }\n\n /**\n * Stop polling for the token list.\n */\n stop() {\n this.stopPolling();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval.\n */\n async #startPolling(): Promise<void> {\n await safelyExecute(() => this.fetchTokenList());\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList());\n }, this.intervalDelay);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @private\n * @param input - The input for the poll.\n * @param input.networkClientId - The ID of the network client triggering the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll({\n networkClientId,\n }: TokenListPollingInput): Promise<void> {\n return this.fetchTokenList(networkClientId);\n }\n\n /**\n * Fetching token list from the Token Service API.\n *\n * @param networkClientId - The ID of the network client triggering the fetch.\n */\n async fetchTokenList(networkClientId?: NetworkClientId): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n let networkClient;\n if (networkClientId) {\n networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n }\n const chainId = networkClient?.configuration.chainId ?? this.chainId;\n try {\n const { tokensChainsCache } = this.state;\n let tokenList: TokenListMap = {};\n const cachedTokens = await safelyExecute(() =>\n this.#fetchFromCache(chainId),\n );\n if (cachedTokens) {\n // Use non-expired cached tokens\n tokenList = { ...cachedTokens };\n } else {\n // Fetch fresh token list\n const tokensFromAPI = await safelyExecute(\n () =>\n fetchTokenListByChainId(\n chainId,\n this.abortController.signal,\n ) as Promise<TokenListToken[]>,\n );\n\n if (!tokensFromAPI) {\n // Fallback to expired cached tokens\n tokenList = { ...(tokensChainsCache[chainId]?.data || {}) };\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache,\n };\n });\n return;\n }\n for (const token of tokensFromAPI) {\n const formattedToken: TokenListToken = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n tokenList[token.address] = formattedToken;\n }\n }\n const updatedTokensChainsCache: TokensChainsCache = {\n ...tokensChainsCache,\n [chainId]: {\n timestamp: Date.now(),\n data: tokenList,\n },\n };\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache: updatedTokensChainsCache,\n };\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Checks if the Cache timestamp is valid,\n * if yes data in cache will be returned\n * otherwise null will be returned.\n * @param chainId - The chain ID of the network for which to fetch the cache.\n * @returns The cached data, or `null` if the cache was expired.\n */\n async #fetchFromCache(chainId: Hex): Promise<TokenListMap | null> {\n const { tokensChainsCache }: TokenListState = this.state;\n const dataCache = tokensChainsCache[chainId];\n const now = Date.now();\n if (\n dataCache?.data &&\n now - dataCache?.timestamp < this.cacheRefreshThreshold\n ) {\n return dataCache.data;\n }\n return null;\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokenList: {},\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
|
|
1
|
+
{"version":3,"file":"TokenListController.mjs","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":";;;;;;AAKA,OAAO,EAAE,aAAa,EAAE,mCAAmC;AAM3D,OAAO,EAAE,+BAA+B,EAAE,qCAAqC;AAE/E,OAAO,EAAE,KAAK,EAAE,oBAAoB;AAEpC,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,sBAAsB,EACvB,yBAAqB;AACtB,OAAO,EAAE,uBAAuB,EAAE,4BAAwB;AAE1D,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7C,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9C,MAAM,IAAI,GAAG,qBAAqB,CAAC;AAsDnC,MAAM,QAAQ,GAAG;IACf,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IAC7C,iBAAiB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IACrD,8BAA8B,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;CACnE,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAmB,EAAE;IAC3D,OAAO;QACL,SAAS,EAAE,EAAE;QACb,iBAAiB,EAAE,EAAE;QACrB,8BAA8B,EAAE,KAAK;KACtC,CAAC;AACJ,CAAC,CAAC;AAOF;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,+BAA+B,EAIvE;IAaC;;;;;;;;;;;OAWG;IACH,YAAY,EACV,OAAO,EACP,8BAA8B,GAAG,KAAK,EACtC,oBAAoB,EACpB,QAAQ,GAAG,gBAAgB,EAC3B,qBAAqB,GAAG,iBAAiB,EACzC,SAAS,EACT,KAAK,GAWN;QACC,KAAK,CAAC;YACJ,IAAI;YACJ,QAAQ;YACR,SAAS;YACT,KAAK,EAAE,EAAE,GAAG,wBAAwB,EAAE,EAAE,GAAG,KAAK,EAAE;SACnD,CAAC,CAAC;;QAhDY,UAAK,GAAG,IAAI,KAAK,EAAE,CAAC;QAiDnC,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;QACnD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,oCAAoC,CAAC,8BAA8B,CAAC,CAAC;QAC1E,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC7C,IAAI,oBAAoB,EAAE;YACxB,gFAAgF;YAChF,kEAAkE;YAClE,oBAAoB,CAAC,KAAK,EAAE,sBAAsB,EAAE,EAAE;gBACpD,MAAM,uBAAA,IAAI,2FAAgC,MAApC,IAAI,EAAiC,sBAAsB,CAAC,CAAC;YACrE,CAAC,CAAC,CAAC;SACJ;aAAM;YACL,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,+BAA+B;YAC/B,gFAAgF;YAChF,kEAAkE;YAClE,KAAK,EAAE,sBAAsB,EAAE,EAAE;gBAC/B,MAAM,uBAAA,IAAI,2FAAgC,MAApC,IAAI,EAAiC,sBAAsB,CAAC,CAAC;YACrE,CAAC,CACF,CAAC;SACH;IACH,CAAC;IAiCD,4FAA4F;IAC5F,qGAAqG;IACrG;;;;OAIG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YACjD,OAAO;SACR;QACD,MAAM,uBAAA,IAAI,mFAAwB,MAA5B,IAAI,CAA0B,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,uBAAA,IAAI,mFAAwB,MAA5B,IAAI,CAA0B,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACH,IAAI;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACM,OAAO;QACd,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACK,WAAW;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SAChC;IACH,CAAC;IAiBD;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAAC,EAAE,OAAO,EAAyB;QACnD,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,OAAY;QAC/B,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC/C,IAAI;YACF,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;YACzC,IAAI,SAAS,GAAiB,EAAE,CAAC;YACjC,iCAAiC;YACjC,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,CAC5C,uBAAA,IAAI,2EAAgB,MAApB,IAAI,EAAiB,OAAO,CAAC,CAC9B,CAAC;YACF,IAAI,YAAY,EAAE;gBAChB,gCAAgC;gBAChC,SAAS,GAAG,EAAE,GAAG,YAAY,EAAE,CAAC;aACjC;iBAAM;gBACL,sCAAsC;gBACtC,MAAM,aAAa,GAAG,MAAM,aAAa,CACvC,GAAG,EAAE,CACH,uBAAuB,CACrB,OAAO,EACP,IAAI,CAAC,eAAe,CAAC,MAAM,CACC,CACjC,CAAC;gBAEF,IAAI,aAAa,EAAE;oBACjB,qDAAqD;oBACrD,SAAS,GAAG,EAAE,CAAC;oBACf,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE;wBACjC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG;4BACzB,GAAG,KAAK;4BACR,WAAW,EAAE,qBAAqB,CAAC,KAAK,CAAC,WAAW,CAAC;4BACrD,OAAO,EAAE,sBAAsB,CAAC;gCAC9B,OAAO;gCACP,YAAY,EAAE,KAAK,CAAC,OAAO;6BAC5B,CAAC;yBACH,CAAC;qBACH;iBACF;qBAAM;oBACL,oCAAoC;oBACpC,SAAS,GAAG,EAAE,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;iBAC7D;aACF;YAED,gFAAgF;YAChF,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;gBACf,OAAO;oBACL,GAAG,IAAI,CAAC,KAAK;oBACb,SAAS,EACP,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS;oBAC7D,iBAAiB,EAAE;wBACjB,GAAG,iBAAiB;wBACpB,CAAC,OAAO,CAAC,EAAE;4BACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;4BACrB,IAAI,EAAE,SAAS;yBAChB;qBACF;iBACF,CAAC;YACJ,CAAC,CAAC,CAAC;SACJ;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;IACH,CAAC;IAsBD;;OAEG;IACH,qBAAqB;QACnB,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;YACf,OAAO;gBACL,GAAG,IAAI,CAAC,KAAK;gBACb,SAAS,EAAE,EAAE;gBACb,iBAAiB,EAAE,EAAE;aACtB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,oCAAoC,CAAC,oBAA6B;QAChE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;YACf,OAAO;gBACL,GAAG,IAAI,CAAC,KAAK;gBACb,8BAA8B,EAAE,oBAAoB;aACrD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF;;AAhOC;;;;;GAKG;AACH,KAAK,8DAAiC,sBAAoC;IACxE,MAAM,qBAAqB,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CACrD,wCAAwC,EACxC,sBAAsB,CAAC,uBAAuB,CAC/C,CAAC;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,qBAAqB,CAAC,aAAa,CAAC;IAExD,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,EAAE;QAC5B,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC7C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,IAAI,CAAC,KAAK,CAAC,8BAA8B,EAAE;YAC7C,IAAI,CAAC,qBAAqB,EAAE,CAAC;SAC9B;aAAM;YACL,4DAA4D;YAC5D,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;gBACf,OAAO;oBACL,GAAG,IAAI,CAAC,KAAK;oBACb,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,EAAE;iBAClE,CAAC;YACJ,CAAC,CAAC,CAAC;SACJ;KACF;AACH,CAAC;AAwDD;;;;GAIG;AACH,KAAK;IACH,mDAAmD;IACnD,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7D,gFAAgF;IAChF,kEAAkE;IAClE,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACvC,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/D,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;AACzB,CAAC;AAgFD;;;;;;GAMG;AACH,KAAK,8CAAiB,OAAY;IAChC,MAAM,EAAE,iBAAiB,EAAE,GAAmB,IAAI,CAAC,KAAK,CAAC;IACzD,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IACE,SAAS,EAAE,IAAI;QACf,GAAG,GAAG,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC,qBAAqB,EACvD;QACA,OAAO,SAAS,CAAC,IAAI,CAAC;KACvB;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AA8BH,eAAe,mBAAmB,CAAC","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type {\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenListByChainId } from './token-service';\n\nconst DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\nexport type TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokenList: TokenListMap;\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = ControllerStateChangeEvent<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerEvents = TokenListStateChange;\n\nexport type GetTokenListState = ControllerGetStateAction<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerActions = GetTokenListState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype AllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type TokenListControllerMessenger = RestrictedControllerMessenger<\n typeof name,\n TokenListControllerActions | AllowedActions,\n TokenListControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\nconst metadata = {\n tokenList: { persist: true, anonymous: true },\n tokensChainsCache: { persist: true, anonymous: true },\n preventPollingOnNetworkRestart: { persist: true, anonymous: true },\n};\n\nexport const getDefaultTokenListState = (): TokenListState => {\n return {\n tokenList: {},\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n };\n};\n\n/** The input to start polling for the {@link TokenListController} */\ntype TokenListPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends StaticIntervalPollingController<TokenListPollingInput>()<\n typeof name,\n TokenListState,\n TokenListControllerMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted controller messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListControllerMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...getDefaultTokenListState(), ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(networkControllerState: NetworkState) {\n const selectedNetworkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkControllerState.selectedNetworkClientId,\n );\n const { chainId } = selectedNetworkClient.configuration;\n\n if (this.chainId !== chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n } else {\n // Ensure tokenList is referencing data from correct network\n this.update(() => {\n return {\n ...this.state,\n tokenList: this.state.tokensChainsCache[this.chainId]?.data || {},\n };\n });\n }\n }\n }\n\n // Eventually we want to remove start/restart/stop controls in favor of new _executePoll API\n // Maintaining these functions for now until we can safely deprecate them for backwards compatibility\n /**\n * Start polling for the token list.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async start() {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Restart polling for the token list.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async restart() {\n this.stopPolling();\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Stop polling for the token list.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n stop() {\n this.stopPolling();\n }\n\n /**\n * This stops any active polling.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * This stops any active polling intervals.\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval for a given chainId (this should be deprecated in favor of _executePoll)\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async #startDeprecatedPolling(): Promise<void> {\n // renaming this to avoid collision with base class\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n }, this.intervalDelay);\n }\n\n /**\n * This starts a new polling loop for any given chain. Under the hood it is deduping polls\n *\n * @private\n * @param input - The input for the poll.\n * @param input.chainId - The chainId of the chain to trigger the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll({ chainId }: TokenListPollingInput): Promise<void> {\n return this.fetchTokenList(chainId);\n }\n\n /**\n * Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)\n *\n * @param chainId - The chainId of the current chain triggering the fetch.\n */\n async fetchTokenList(chainId: Hex): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n const { tokensChainsCache } = this.state;\n let tokenList: TokenListMap = {};\n // Attempt to fetch cached tokens\n const cachedTokens = await safelyExecute(() =>\n this.#fetchFromCache(chainId),\n );\n if (cachedTokens) {\n // Use non-expired cached tokens\n tokenList = { ...cachedTokens };\n } else {\n // Fetch fresh token list from the API\n const tokensFromAPI = await safelyExecute(\n () =>\n fetchTokenListByChainId(\n chainId,\n this.abortController.signal,\n ) as Promise<TokenListToken[]>,\n );\n\n if (tokensFromAPI) {\n // Format tokens from API (HTTP) and update tokenList\n tokenList = {};\n for (const token of tokensFromAPI) {\n tokenList[token.address] = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n }\n } else {\n // Fallback to expired cached tokens\n tokenList = { ...(tokensChainsCache[chainId]?.data || {}) };\n }\n }\n\n // Update the state with a single update for both tokenList and tokenChainsCache\n this.update(() => {\n return {\n ...this.state,\n tokenList:\n this.chainId === chainId ? tokenList : this.state.tokenList,\n tokensChainsCache: {\n ...tokensChainsCache,\n [chainId]: {\n timestamp: Date.now(),\n data: tokenList,\n },\n },\n };\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Checks if the Cache timestamp is valid,\n * if yes data in cache will be returned\n * otherwise null will be returned.\n * @param chainId - The chain ID of the network for which to fetch the cache.\n * @returns The cached data, or `null` if the cache was expired.\n */\n async #fetchFromCache(chainId: Hex): Promise<TokenListMap | null> {\n const { tokensChainsCache }: TokenListState = this.state;\n const dataCache = tokensChainsCache[chainId];\n const now = Date.now();\n if (\n dataCache?.data &&\n now - dataCache?.timestamp < this.cacheRefreshThreshold\n ) {\n return dataCache.data;\n }\n return null;\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokenList: {},\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
|
|
@@ -206,13 +206,26 @@ class TokenRatesController extends (0, polling_controller_1.StaticIntervalPollin
|
|
|
206
206
|
* Updates token rates for the given networkClientId
|
|
207
207
|
*
|
|
208
208
|
* @param input - The input for the poll.
|
|
209
|
-
* @param input.
|
|
209
|
+
* @param input.chainId - The chain id to poll token rates on.
|
|
210
210
|
*/
|
|
211
|
-
async _executePoll({
|
|
212
|
-
const
|
|
211
|
+
async _executePoll({ chainId }) {
|
|
212
|
+
const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
|
|
213
|
+
const networkConfiguration = networkConfigurationsByChainId[chainId];
|
|
214
|
+
if (!networkConfiguration) {
|
|
215
|
+
console.error(`TokenRatesController: No network configuration found for chainId ${chainId}`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
213
218
|
await this.updateExchangeRatesByChainId({
|
|
214
|
-
chainId
|
|
215
|
-
nativeCurrency:
|
|
219
|
+
chainId,
|
|
220
|
+
nativeCurrency: networkConfiguration.nativeCurrency,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Reset the controller state to the default state.
|
|
225
|
+
*/
|
|
226
|
+
resetState() {
|
|
227
|
+
this.update(() => {
|
|
228
|
+
return (0, exports.getDefaultTokenRatesControllerState)();
|
|
216
229
|
});
|
|
217
230
|
}
|
|
218
231
|
}
|
|
@@ -222,14 +235,29 @@ _TokenRatesController_handle = new WeakMap(), _TokenRatesController_pollState =
|
|
|
222
235
|
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
223
236
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
224
237
|
async ({ allTokens, allDetectedTokens }) => {
|
|
225
|
-
|
|
238
|
+
if (__classPrivateFieldGet(this, _TokenRatesController_disabled, "f")) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const chainIds = [
|
|
242
|
+
...new Set([
|
|
243
|
+
...Object.keys(allTokens),
|
|
244
|
+
...Object.keys(allDetectedTokens),
|
|
245
|
+
]),
|
|
246
|
+
];
|
|
247
|
+
const chainIdsToUpdate = chainIds.filter((chainId) => !(0, lodash_1.isEqual)(__classPrivateFieldGet(this, _TokenRatesController_allTokens, "f")[chainId], allTokens[chainId]) ||
|
|
248
|
+
!(0, lodash_1.isEqual)(__classPrivateFieldGet(this, _TokenRatesController_allDetectedTokens, "f")[chainId], allDetectedTokens[chainId]));
|
|
226
249
|
__classPrivateFieldSet(this, _TokenRatesController_allTokens, allTokens, "f");
|
|
227
250
|
__classPrivateFieldSet(this, _TokenRatesController_allDetectedTokens, allDetectedTokens, "f");
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
251
|
+
const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
|
|
252
|
+
await Promise.allSettled(chainIdsToUpdate.map(async (chainId) => {
|
|
253
|
+
const nativeCurrency = networkConfigurationsByChainId[chainId]?.nativeCurrency;
|
|
254
|
+
if (nativeCurrency) {
|
|
255
|
+
await this.updateExchangeRatesByChainId({
|
|
256
|
+
chainId: chainId,
|
|
257
|
+
nativeCurrency,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}));
|
|
233
261
|
}, ({ allTokens, allDetectedTokens }) => {
|
|
234
262
|
return { allTokens, allDetectedTokens };
|
|
235
263
|
});
|
|
@@ -324,6 +352,7 @@ async function _TokenRatesController_fetchAndMapExchangeRates({ tokenAddresses,
|
|
|
324
352
|
});
|
|
325
353
|
}
|
|
326
354
|
return await __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency).call(this, {
|
|
355
|
+
chainId,
|
|
327
356
|
tokenAddresses,
|
|
328
357
|
nativeCurrency,
|
|
329
358
|
});
|
|
@@ -387,17 +416,18 @@ async function _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeC
|
|
|
387
416
|
* API, then convert the prices to our desired native currency.
|
|
388
417
|
*
|
|
389
418
|
* @param args - The arguments to this function.
|
|
419
|
+
* @param args.chainId - The chain id to fetch prices for.
|
|
390
420
|
* @param args.tokenAddresses - Addresses for tokens.
|
|
391
421
|
* @param args.nativeCurrency - The native currency in which to request
|
|
392
422
|
* prices.
|
|
393
423
|
* @returns A map of the token addresses (as checksums) to their prices in the
|
|
394
424
|
* native currency.
|
|
395
425
|
*/
|
|
396
|
-
async function _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency({ tokenAddresses, nativeCurrency, }) {
|
|
426
|
+
async function _TokenRatesController_fetchAndMapExchangeRatesForUnsupportedNativeCurrency({ chainId, tokenAddresses, nativeCurrency, }) {
|
|
397
427
|
const [contractExchangeInformations, fallbackCurrencyToNativeCurrencyConversionRate,] = await Promise.all([
|
|
398
428
|
__classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_fetchAndMapExchangeRatesForSupportedNativeCurrency).call(this, {
|
|
399
429
|
tokenAddresses,
|
|
400
|
-
chainId
|
|
430
|
+
chainId,
|
|
401
431
|
nativeCurrency: controller_utils_1.FALL_BACK_VS_CURRENCY,
|
|
402
432
|
}),
|
|
403
433
|
getCurrencyConversionRate({
|