@metamask/assets-controllers 1.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 +22 -0
- package/LICENSE +20 -0
- package/README.md +30 -0
- package/dist/AccountTrackerController.d.ts +88 -0
- package/dist/AccountTrackerController.js +138 -0
- package/dist/AccountTrackerController.js.map +1 -0
- package/dist/AssetsContractController.d.ts +176 -0
- package/dist/AssetsContractController.js +314 -0
- package/dist/AssetsContractController.js.map +1 -0
- package/dist/CurrencyRateController.d.ts +98 -0
- package/dist/CurrencyRateController.js +193 -0
- package/dist/CurrencyRateController.js.map +1 -0
- package/dist/NftController.d.ts +409 -0
- package/dist/NftController.js +835 -0
- package/dist/NftController.js.map +1 -0
- package/dist/NftDetectionController.d.ts +179 -0
- package/dist/NftDetectionController.js +204 -0
- package/dist/NftDetectionController.js.map +1 -0
- package/dist/Standards/ERC20Standard.d.ts +42 -0
- package/dist/Standards/ERC20Standard.js +121 -0
- package/dist/Standards/ERC20Standard.js.map +1 -0
- package/dist/Standards/NftStandards/ERC1155/ERC1155Standard.d.ts +78 -0
- package/dist/Standards/NftStandards/ERC1155/ERC1155Standard.js +148 -0
- package/dist/Standards/NftStandards/ERC1155/ERC1155Standard.js.map +1 -0
- package/dist/Standards/NftStandards/ERC721/ERC721Standard.d.ts +88 -0
- package/dist/Standards/NftStandards/ERC721/ERC721Standard.js +182 -0
- package/dist/Standards/NftStandards/ERC721/ERC721Standard.js.map +1 -0
- package/dist/Standards/standards-types.d.ts +14 -0
- package/dist/Standards/standards-types.js +3 -0
- package/dist/Standards/standards-types.js.map +1 -0
- package/dist/TokenBalancesController.d.ts +69 -0
- package/dist/TokenBalancesController.js +94 -0
- package/dist/TokenBalancesController.js.map +1 -0
- package/dist/TokenDetectionController.d.ts +84 -0
- package/dist/TokenDetectionController.js +185 -0
- package/dist/TokenDetectionController.js.map +1 -0
- package/dist/TokenListController.d.ts +114 -0
- package/dist/TokenListController.js +256 -0
- package/dist/TokenListController.js.map +1 -0
- package/dist/TokenRatesController.d.ts +167 -0
- package/dist/TokenRatesController.js +284 -0
- package/dist/TokenRatesController.js.map +1 -0
- package/dist/TokensController.d.ts +238 -0
- package/dist/TokensController.js +530 -0
- package/dist/TokensController.js.map +1 -0
- package/dist/assetsUtil.d.ts +106 -0
- package/dist/assetsUtil.js +228 -0
- package/dist/assetsUtil.js.map +1 -0
- package/dist/crypto-compare.d.ts +12 -0
- package/dist/crypto-compare.js +67 -0
- package/dist/crypto-compare.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/token-service.d.ts +29 -0
- package/dist/token-service.js +134 -0
- package/dist/token-service.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
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
|
+
var _TokenListController_instances, _TokenListController_onNetworkStateChangeCallback;
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.TokenListController = void 0;
|
|
19
|
+
const async_mutex_1 = require("async-mutex");
|
|
20
|
+
const abort_controller_1 = require("abort-controller");
|
|
21
|
+
const base_controller_1 = require("@metamask/base-controller");
|
|
22
|
+
const controller_utils_1 = require("@metamask/controller-utils");
|
|
23
|
+
const assetsUtil_1 = require("./assetsUtil");
|
|
24
|
+
const token_service_1 = require("./token-service");
|
|
25
|
+
const DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;
|
|
26
|
+
const DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;
|
|
27
|
+
const name = 'TokenListController';
|
|
28
|
+
const metadata = {
|
|
29
|
+
tokenList: { persist: true, anonymous: true },
|
|
30
|
+
tokensChainsCache: { persist: true, anonymous: true },
|
|
31
|
+
preventPollingOnNetworkRestart: { persist: true, anonymous: true },
|
|
32
|
+
};
|
|
33
|
+
const defaultState = {
|
|
34
|
+
tokenList: {},
|
|
35
|
+
tokensChainsCache: {},
|
|
36
|
+
preventPollingOnNetworkRestart: false,
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Controller that passively polls on a set interval for the list of tokens from metaswaps api
|
|
40
|
+
*/
|
|
41
|
+
class TokenListController extends base_controller_1.BaseControllerV2 {
|
|
42
|
+
/**
|
|
43
|
+
* Creates a TokenListController instance.
|
|
44
|
+
*
|
|
45
|
+
* @param options - The controller options.
|
|
46
|
+
* @param options.chainId - The chain ID of the current network.
|
|
47
|
+
* @param options.onNetworkStateChange - A function for registering an event handler for network state changes.
|
|
48
|
+
* @param options.interval - The polling interval, in milliseconds.
|
|
49
|
+
* @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.
|
|
50
|
+
* @param options.messenger - A restricted controller messenger.
|
|
51
|
+
* @param options.state - Initial state to set on this controller.
|
|
52
|
+
* @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.
|
|
53
|
+
*/
|
|
54
|
+
constructor({ chainId, preventPollingOnNetworkRestart = false, onNetworkStateChange, interval = DEFAULT_INTERVAL, cacheRefreshThreshold = DEFAULT_THRESHOLD, messenger, state, }) {
|
|
55
|
+
super({
|
|
56
|
+
name,
|
|
57
|
+
metadata,
|
|
58
|
+
messenger,
|
|
59
|
+
state: Object.assign(Object.assign({}, defaultState), state),
|
|
60
|
+
});
|
|
61
|
+
_TokenListController_instances.add(this);
|
|
62
|
+
this.mutex = new async_mutex_1.Mutex();
|
|
63
|
+
this.intervalDelay = interval;
|
|
64
|
+
this.cacheRefreshThreshold = cacheRefreshThreshold;
|
|
65
|
+
this.chainId = chainId;
|
|
66
|
+
this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);
|
|
67
|
+
this.abortController = new abort_controller_1.AbortController();
|
|
68
|
+
if (onNetworkStateChange) {
|
|
69
|
+
onNetworkStateChange((networkStateOrProviderConfig) => __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
// this check for "provider" is for testing purposes, since in the extension this callback will receive
|
|
71
|
+
// an object typed as NetworkState but within repo we can only simulate as if the callback receives an
|
|
72
|
+
// object typed as ProviderConfig
|
|
73
|
+
if ('provider' in networkStateOrProviderConfig) {
|
|
74
|
+
yield __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_onNetworkStateChangeCallback).call(this, networkStateOrProviderConfig.provider);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
yield __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_onNetworkStateChangeCallback).call(this, networkStateOrProviderConfig);
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.messagingSystem.subscribe('NetworkController:providerChange', (providerConfig) => __awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
yield __classPrivateFieldGet(this, _TokenListController_instances, "m", _TokenListController_onNetworkStateChangeCallback).call(this, providerConfig);
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Start polling for the token list.
|
|
89
|
+
*/
|
|
90
|
+
start() {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
if (!(0, assetsUtil_1.isTokenListSupportedForNetwork)(this.chainId)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
yield this.startPolling();
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Restart polling for the token list.
|
|
100
|
+
*/
|
|
101
|
+
restart() {
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
this.stopPolling();
|
|
104
|
+
yield this.startPolling();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Stop polling for the token list.
|
|
109
|
+
*/
|
|
110
|
+
stop() {
|
|
111
|
+
this.stopPolling();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Prepare to discard this controller.
|
|
115
|
+
*
|
|
116
|
+
* This stops any active polling.
|
|
117
|
+
*/
|
|
118
|
+
destroy() {
|
|
119
|
+
super.destroy();
|
|
120
|
+
this.stopPolling();
|
|
121
|
+
}
|
|
122
|
+
stopPolling() {
|
|
123
|
+
if (this.intervalId) {
|
|
124
|
+
clearInterval(this.intervalId);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Starts a new polling interval.
|
|
129
|
+
*/
|
|
130
|
+
startPolling() {
|
|
131
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
yield (0, controller_utils_1.safelyExecute)(() => this.fetchTokenList());
|
|
133
|
+
this.intervalId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
134
|
+
yield (0, controller_utils_1.safelyExecute)(() => this.fetchTokenList());
|
|
135
|
+
}), this.intervalDelay);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Fetching token list from the Token Service API.
|
|
140
|
+
*/
|
|
141
|
+
fetchTokenList() {
|
|
142
|
+
var _a;
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
const releaseLock = yield this.mutex.acquire();
|
|
145
|
+
try {
|
|
146
|
+
const { tokensChainsCache } = this.state;
|
|
147
|
+
let tokenList = {};
|
|
148
|
+
const cachedTokens = yield (0, controller_utils_1.safelyExecute)(() => this.fetchFromCache());
|
|
149
|
+
if (cachedTokens) {
|
|
150
|
+
// Use non-expired cached tokens
|
|
151
|
+
tokenList = Object.assign({}, cachedTokens);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// Fetch fresh token list
|
|
155
|
+
const tokensFromAPI = yield (0, controller_utils_1.safelyExecute)(() => (0, token_service_1.fetchTokenList)(this.chainId, this.abortController.signal));
|
|
156
|
+
if (!tokensFromAPI) {
|
|
157
|
+
// Fallback to expired cached tokens
|
|
158
|
+
tokenList = Object.assign({}, (((_a = tokensChainsCache[this.chainId]) === null || _a === void 0 ? void 0 : _a.data) || {}));
|
|
159
|
+
this.update(() => {
|
|
160
|
+
return Object.assign(Object.assign({}, this.state), { tokenList,
|
|
161
|
+
tokensChainsCache });
|
|
162
|
+
});
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Filtering out tokens with less than 3 occurrences and native tokens
|
|
166
|
+
const filteredTokenList = tokensFromAPI.filter((token) => token.occurrences &&
|
|
167
|
+
token.occurrences >= 3 &&
|
|
168
|
+
token.address !== '0x0000000000000000000000000000000000000000');
|
|
169
|
+
// Removing the tokens with symbol conflicts
|
|
170
|
+
const symbolsList = filteredTokenList.map((token) => token.symbol);
|
|
171
|
+
const duplicateSymbols = [
|
|
172
|
+
...new Set(symbolsList.filter((symbol, index) => symbolsList.indexOf(symbol) !== index)),
|
|
173
|
+
];
|
|
174
|
+
const uniqueTokenList = filteredTokenList.filter((token) => !duplicateSymbols.includes(token.symbol));
|
|
175
|
+
for (const token of uniqueTokenList) {
|
|
176
|
+
const formattedToken = Object.assign(Object.assign({}, token), { aggregators: (0, assetsUtil_1.formatAggregatorNames)(token.aggregators), iconUrl: (0, assetsUtil_1.formatIconUrlWithProxy)({
|
|
177
|
+
chainId: this.chainId,
|
|
178
|
+
tokenAddress: token.address,
|
|
179
|
+
}) });
|
|
180
|
+
tokenList[token.address] = formattedToken;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const updatedTokensChainsCache = Object.assign(Object.assign({}, tokensChainsCache), { [this.chainId]: {
|
|
184
|
+
timestamp: Date.now(),
|
|
185
|
+
data: tokenList,
|
|
186
|
+
} });
|
|
187
|
+
this.update(() => {
|
|
188
|
+
return Object.assign(Object.assign({}, this.state), { tokenList, tokensChainsCache: updatedTokensChainsCache });
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
releaseLock();
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Checks if the Cache timestamp is valid,
|
|
198
|
+
* if yes data in cache will be returned
|
|
199
|
+
* otherwise null will be returned.
|
|
200
|
+
*
|
|
201
|
+
* @returns The cached data, or `null` if the cache was expired.
|
|
202
|
+
*/
|
|
203
|
+
fetchFromCache() {
|
|
204
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
205
|
+
const { tokensChainsCache } = this.state;
|
|
206
|
+
const dataCache = tokensChainsCache[this.chainId];
|
|
207
|
+
const now = Date.now();
|
|
208
|
+
if ((dataCache === null || dataCache === void 0 ? void 0 : dataCache.data) &&
|
|
209
|
+
now - (dataCache === null || dataCache === void 0 ? void 0 : dataCache.timestamp) < this.cacheRefreshThreshold) {
|
|
210
|
+
return dataCache.data;
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Clearing tokenList and tokensChainsCache explicitly.
|
|
217
|
+
*/
|
|
218
|
+
clearingTokenListData() {
|
|
219
|
+
this.update(() => {
|
|
220
|
+
return Object.assign(Object.assign({}, this.state), { tokenList: {}, tokensChainsCache: {} });
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Updates preventPollingOnNetworkRestart from extension.
|
|
225
|
+
*
|
|
226
|
+
* @param shouldPreventPolling - Determine whether to prevent polling on network change
|
|
227
|
+
*/
|
|
228
|
+
updatePreventPollingOnNetworkRestart(shouldPreventPolling) {
|
|
229
|
+
this.update(() => {
|
|
230
|
+
return Object.assign(Object.assign({}, this.state), { preventPollingOnNetworkRestart: shouldPreventPolling });
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
exports.TokenListController = TokenListController;
|
|
235
|
+
_TokenListController_instances = new WeakSet(), _TokenListController_onNetworkStateChangeCallback = function _TokenListController_onNetworkStateChangeCallback(providerConfig) {
|
|
236
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
237
|
+
if (this.chainId !== providerConfig.chainId) {
|
|
238
|
+
this.abortController.abort();
|
|
239
|
+
this.abortController = new abort_controller_1.AbortController();
|
|
240
|
+
this.chainId = providerConfig.chainId;
|
|
241
|
+
if (this.state.preventPollingOnNetworkRestart) {
|
|
242
|
+
this.clearingTokenListData();
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// Ensure tokenList is referencing data from correct network
|
|
246
|
+
this.update(() => {
|
|
247
|
+
var _a;
|
|
248
|
+
return Object.assign(Object.assign({}, this.state), { tokenList: ((_a = this.state.tokensChainsCache[this.chainId]) === null || _a === void 0 ? void 0 : _a.data) || {} });
|
|
249
|
+
});
|
|
250
|
+
yield this.restart();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
exports.default = TokenListController;
|
|
256
|
+
//# sourceMappingURL=TokenListController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenListController.js","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Patch } from 'immer';\nimport { Mutex } from 'async-mutex';\nimport { AbortController as WhatwgAbortController } from 'abort-controller';\nimport {\n BaseControllerV2,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport {\n NetworkControllerProviderChangeEvent,\n NetworkState,\n ProviderConfig,\n} from '@metamask/network-controller';\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenList } 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};\ntype TokensChainsCache = {\n [chainSlug: string]: DataCache;\n};\n\nexport type TokenListState = {\n tokenList: TokenListMap;\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = {\n type: `${typeof name}:stateChange`;\n payload: [TokenListState, Patch[]];\n};\n\nexport type GetTokenListState = {\n type: `${typeof name}:getState`;\n handler: () => TokenListState;\n};\n\ntype TokenListMessenger = RestrictedControllerMessenger<\n typeof name,\n GetTokenListState,\n TokenListStateChange | NetworkControllerProviderChangeEvent,\n never,\n TokenListStateChange['type'] | NetworkControllerProviderChangeEvent['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\nconst defaultState: TokenListState = {\n tokenList: {},\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\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 BaseControllerV2<\n typeof name,\n TokenListState,\n TokenListMessenger\n> {\n private mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private intervalDelay: number;\n\n private cacheRefreshThreshold: number;\n\n private chainId: string;\n\n private abortController: WhatwgAbortController;\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: string;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState | ProviderConfig) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.intervalDelay = interval;\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new WhatwgAbortController();\n if (onNetworkStateChange) {\n onNetworkStateChange(async (networkStateOrProviderConfig) => {\n // this check for \"provider\" is for testing purposes, since in the extension this callback will receive\n // an object typed as NetworkState but within repo we can only simulate as if the callback receives an\n // object typed as ProviderConfig\n if ('provider' in networkStateOrProviderConfig) {\n await this.#onNetworkStateChangeCallback(\n networkStateOrProviderConfig.provider,\n );\n } else {\n await this.#onNetworkStateChangeCallback(\n networkStateOrProviderConfig,\n );\n }\n });\n } else {\n this.messagingSystem.subscribe(\n 'NetworkController:providerChange',\n async (providerConfig) => {\n await this.#onNetworkStateChangeCallback(providerConfig);\n },\n );\n }\n }\n\n /**\n * Updates state and restart polling when updates are received through NetworkController subscription.\n *\n * @param providerConfig - the configuration for a provider containing critical network info.\n */\n async #onNetworkStateChangeCallback(providerConfig: ProviderConfig) {\n if (this.chainId !== providerConfig.chainId) {\n this.abortController.abort();\n this.abortController = new WhatwgAbortController();\n this.chainId = providerConfig.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 private async startPolling(): Promise<void> {\n await safelyExecute(() => this.fetchTokenList());\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 async fetchTokenList(): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n const { tokensChainsCache } = this.state;\n let tokenList: TokenListMap = {};\n const cachedTokens: TokenListMap = await safelyExecute(() =>\n this.fetchFromCache(),\n );\n if (cachedTokens) {\n // Use non-expired cached tokens\n tokenList = { ...cachedTokens };\n } else {\n // Fetch fresh token list\n const tokensFromAPI: TokenListToken[] = await safelyExecute(() =>\n fetchTokenList(this.chainId, this.abortController.signal),\n );\n\n if (!tokensFromAPI) {\n // Fallback to expired cached tokens\n tokenList = { ...(tokensChainsCache[this.chainId]?.data || {}) };\n\n this.update(() => {\n return {\n ...this.state,\n tokenList,\n tokensChainsCache,\n };\n });\n return;\n }\n // Filtering out tokens with less than 3 occurrences and native tokens\n const filteredTokenList = tokensFromAPI.filter(\n (token) =>\n token.occurrences &&\n token.occurrences >= 3 &&\n token.address !== '0x0000000000000000000000000000000000000000',\n );\n // Removing the tokens with symbol conflicts\n const symbolsList = filteredTokenList.map((token) => token.symbol);\n const duplicateSymbols = [\n ...new Set(\n symbolsList.filter(\n (symbol, index) => symbolsList.indexOf(symbol) !== index,\n ),\n ),\n ];\n const uniqueTokenList = filteredTokenList.filter(\n (token) => !duplicateSymbols.includes(token.symbol),\n );\n for (const token of uniqueTokenList) {\n const formattedToken: TokenListToken = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId: this.chainId,\n tokenAddress: token.address,\n }),\n };\n tokenList[token.address] = formattedToken;\n }\n }\n const updatedTokensChainsCache: TokensChainsCache = {\n ...tokensChainsCache,\n [this.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 *\n * @returns The cached data, or `null` if the cache was expired.\n */\n async fetchFromCache(): Promise<TokenListMap | null> {\n const { tokensChainsCache }: TokenListState = this.state;\n const dataCache = tokensChainsCache[this.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"]}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { BaseController, BaseConfig, BaseState } from '@metamask/base-controller';
|
|
2
|
+
import type { NetworkState } from '@metamask/network-controller';
|
|
3
|
+
import type { TokensState } from './TokensController';
|
|
4
|
+
import type { CurrencyRateState } from './CurrencyRateController';
|
|
5
|
+
/**
|
|
6
|
+
* @type CoinGeckoResponse
|
|
7
|
+
*
|
|
8
|
+
* CoinGecko API response representation
|
|
9
|
+
*/
|
|
10
|
+
export interface CoinGeckoResponse {
|
|
11
|
+
[address: string]: {
|
|
12
|
+
[currency: string]: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @type CoinGeckoPlatform
|
|
17
|
+
*
|
|
18
|
+
* CoinGecko supported platform API representation
|
|
19
|
+
*/
|
|
20
|
+
export interface CoinGeckoPlatform {
|
|
21
|
+
id: string;
|
|
22
|
+
chain_identifier: null | number;
|
|
23
|
+
name: string;
|
|
24
|
+
shortname: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @type Token
|
|
28
|
+
*
|
|
29
|
+
* Token representation
|
|
30
|
+
* @property address - Hex address of the token contract
|
|
31
|
+
* @property decimals - Number of decimals the token uses
|
|
32
|
+
* @property symbol - Symbol of the token
|
|
33
|
+
* @property image - Image of the token, url or bit32 image
|
|
34
|
+
*/
|
|
35
|
+
export interface Token {
|
|
36
|
+
address: string;
|
|
37
|
+
decimals: number;
|
|
38
|
+
symbol: string;
|
|
39
|
+
aggregators?: string[];
|
|
40
|
+
image?: string;
|
|
41
|
+
balanceError?: unknown;
|
|
42
|
+
isERC721?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @type TokenRatesConfig
|
|
46
|
+
*
|
|
47
|
+
* Token rates controller configuration
|
|
48
|
+
* @property interval - Polling interval used to fetch new token rates
|
|
49
|
+
* @property nativeCurrency - Current native currency selected to use base of rates
|
|
50
|
+
* @property chainId - Current network chainId
|
|
51
|
+
* @property tokens - List of tokens to track exchange rates for
|
|
52
|
+
* @property threshold - Threshold to invalidate the supportedChains
|
|
53
|
+
*/
|
|
54
|
+
export interface TokenRatesConfig extends BaseConfig {
|
|
55
|
+
interval: number;
|
|
56
|
+
nativeCurrency: string;
|
|
57
|
+
chainId: string;
|
|
58
|
+
tokens: Token[];
|
|
59
|
+
threshold: number;
|
|
60
|
+
}
|
|
61
|
+
interface ContractExchangeRates {
|
|
62
|
+
[address: string]: number | undefined;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* @type TokenRatesState
|
|
66
|
+
*
|
|
67
|
+
* Token rates controller state
|
|
68
|
+
* @property contractExchangeRates - Hash of token contract addresses to exchange rates
|
|
69
|
+
* @property supportedChains - Cached chain data
|
|
70
|
+
*/
|
|
71
|
+
export interface TokenRatesState extends BaseState {
|
|
72
|
+
contractExchangeRates: ContractExchangeRates;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Controller that passively polls on a set interval for token-to-fiat exchange rates
|
|
76
|
+
* for tokens stored in the TokensController
|
|
77
|
+
*/
|
|
78
|
+
export declare class TokenRatesController extends BaseController<TokenRatesConfig, TokenRatesState> {
|
|
79
|
+
private handle?;
|
|
80
|
+
private tokenList;
|
|
81
|
+
private supportedChains;
|
|
82
|
+
private supportedVsCurrencies;
|
|
83
|
+
/**
|
|
84
|
+
* Name of this controller used during composition
|
|
85
|
+
*/
|
|
86
|
+
name: string;
|
|
87
|
+
/**
|
|
88
|
+
* Creates a TokenRatesController instance.
|
|
89
|
+
*
|
|
90
|
+
* @param options - The controller options.
|
|
91
|
+
* @param options.onTokensStateChange - Allows subscribing to token controller state changes.
|
|
92
|
+
* @param options.onCurrencyRateStateChange - Allows subscribing to currency rate controller state changes.
|
|
93
|
+
* @param options.onNetworkStateChange - Allows subscribing to network state changes.
|
|
94
|
+
* @param config - Initial options used to configure this controller.
|
|
95
|
+
* @param state - Initial state to set on this controller.
|
|
96
|
+
*/
|
|
97
|
+
constructor({ onTokensStateChange, onCurrencyRateStateChange, onNetworkStateChange, }: {
|
|
98
|
+
onTokensStateChange: (listener: (tokensState: TokensState) => void) => void;
|
|
99
|
+
onCurrencyRateStateChange: (listener: (currencyRateState: CurrencyRateState) => void) => void;
|
|
100
|
+
onNetworkStateChange: (listener: (networkState: NetworkState) => void) => void;
|
|
101
|
+
}, config?: Partial<TokenRatesConfig>, state?: Partial<TokenRatesState>);
|
|
102
|
+
/**
|
|
103
|
+
* Sets a new polling interval.
|
|
104
|
+
*
|
|
105
|
+
* @param interval - Polling interval used to fetch new token rates.
|
|
106
|
+
*/
|
|
107
|
+
poll(interval?: number): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Sets a new chainId.
|
|
110
|
+
*
|
|
111
|
+
* TODO: Replace this with a method.
|
|
112
|
+
*
|
|
113
|
+
* @param _chainId - The current chain ID.
|
|
114
|
+
*/
|
|
115
|
+
set chainId(_chainId: string);
|
|
116
|
+
get chainId(): string;
|
|
117
|
+
/**
|
|
118
|
+
* Sets a new token list to track prices.
|
|
119
|
+
*
|
|
120
|
+
* TODO: Replace this with a method.
|
|
121
|
+
*
|
|
122
|
+
* @param tokens - List of tokens to track exchange rates for.
|
|
123
|
+
*/
|
|
124
|
+
set tokens(tokens: Token[]);
|
|
125
|
+
get tokens(): Token[];
|
|
126
|
+
/**
|
|
127
|
+
* Fetches a pairs of token address and native currency.
|
|
128
|
+
*
|
|
129
|
+
* @param chainSlug - Chain string identifier.
|
|
130
|
+
* @param vsCurrency - Query according to tokens in tokenList and native currency.
|
|
131
|
+
* @returns The exchange rates for the given pairs.
|
|
132
|
+
*/
|
|
133
|
+
fetchExchangeRate(chainSlug: string, vsCurrency: string): Promise<CoinGeckoResponse>;
|
|
134
|
+
/**
|
|
135
|
+
* Checks if the current native currency is a supported vs currency to use
|
|
136
|
+
* to query for token exchange rates.
|
|
137
|
+
*
|
|
138
|
+
* @param nativeCurrency - The native currency of the currently active network.
|
|
139
|
+
* @returns A boolean indicating whether it's a supported vsCurrency.
|
|
140
|
+
*/
|
|
141
|
+
private checkIsSupportedVsCurrency;
|
|
142
|
+
/**
|
|
143
|
+
* Gets current chain ID slug from cached supported platforms CoinGecko API response.
|
|
144
|
+
* If cached supported platforms response is stale, fetches and updates it.
|
|
145
|
+
*
|
|
146
|
+
* @returns The CoinGecko slug for the current chain ID.
|
|
147
|
+
*/
|
|
148
|
+
getChainSlug(): Promise<string | null>;
|
|
149
|
+
/**
|
|
150
|
+
* Updates exchange rates for all tokens.
|
|
151
|
+
*/
|
|
152
|
+
updateExchangeRates(): Promise<void>;
|
|
153
|
+
/**
|
|
154
|
+
* Checks if the active network's native currency is supported by the coingecko API.
|
|
155
|
+
* If supported, it fetches and maps contractExchange rates to a format to be consumed by the UI.
|
|
156
|
+
* If not supported, it fetches contractExchange rates and maps them from token/fallback-currency
|
|
157
|
+
* to token/nativeCurrency.
|
|
158
|
+
*
|
|
159
|
+
* @param nativeCurrency - The native currency of the currently active network.
|
|
160
|
+
* @param slug - The unique slug used to id the chain by the coingecko api
|
|
161
|
+
* should be used to query token exchange rates.
|
|
162
|
+
* @returns An object with conversion rates for each token
|
|
163
|
+
* related to the network's native currency.
|
|
164
|
+
*/
|
|
165
|
+
fetchAndMapExchangeRates(nativeCurrency: string, slug: string): Promise<ContractExchangeRates>;
|
|
166
|
+
}
|
|
167
|
+
export default TokenRatesController;
|