@metamask/assets-controller 0.2.0 → 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 +17 -1
- package/dist/AssetsController-method-action-types.cjs +7 -0
- package/dist/AssetsController-method-action-types.cjs.map +1 -0
- package/dist/AssetsController-method-action-types.d.cts +78 -0
- package/dist/AssetsController-method-action-types.d.cts.map +1 -0
- package/dist/AssetsController-method-action-types.d.mts +78 -0
- package/dist/AssetsController-method-action-types.d.mts.map +1 -0
- package/dist/AssetsController-method-action-types.mjs +6 -0
- package/dist/AssetsController-method-action-types.mjs.map +1 -0
- package/dist/AssetsController.cjs +201 -237
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts +29 -92
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts +29 -92
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +201 -237
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/AbstractDataSource.cjs +8 -0
- package/dist/data-sources/AbstractDataSource.cjs.map +1 -1
- package/dist/data-sources/AbstractDataSource.d.cts +16 -1
- package/dist/data-sources/AbstractDataSource.d.cts.map +1 -1
- package/dist/data-sources/AbstractDataSource.d.mts +16 -1
- package/dist/data-sources/AbstractDataSource.d.mts.map +1 -1
- package/dist/data-sources/AbstractDataSource.mjs +8 -0
- package/dist/data-sources/AbstractDataSource.mjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.cjs +25 -99
- package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.cts +5 -67
- package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.mts +5 -67
- package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.mjs +24 -97
- package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.cjs +138 -45
- package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.cts +19 -66
- package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.mts +19 -66
- package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.mjs +138 -45
- package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
- package/dist/data-sources/PriceDataSource.cjs +22 -44
- package/dist/data-sources/PriceDataSource.cjs.map +1 -1
- package/dist/data-sources/PriceDataSource.d.cts +6 -89
- package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
- package/dist/data-sources/PriceDataSource.d.mts +6 -89
- package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
- package/dist/data-sources/PriceDataSource.mjs +22 -44
- package/dist/data-sources/PriceDataSource.mjs.map +1 -1
- package/dist/data-sources/RpcDataSource.cjs +64 -102
- package/dist/data-sources/RpcDataSource.cjs.map +1 -1
- package/dist/data-sources/RpcDataSource.d.cts +16 -55
- package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
- package/dist/data-sources/RpcDataSource.d.mts +16 -55
- package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
- package/dist/data-sources/RpcDataSource.mjs +64 -102
- package/dist/data-sources/RpcDataSource.mjs.map +1 -1
- package/dist/data-sources/SnapDataSource.cjs +32 -30
- package/dist/data-sources/SnapDataSource.cjs.map +1 -1
- package/dist/data-sources/SnapDataSource.d.cts +7 -44
- package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
- package/dist/data-sources/SnapDataSource.d.mts +7 -44
- package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
- package/dist/data-sources/SnapDataSource.mjs +32 -30
- package/dist/data-sources/SnapDataSource.mjs.map +1 -1
- package/dist/data-sources/TokenDataSource.cjs +3 -16
- package/dist/data-sources/TokenDataSource.cjs.map +1 -1
- package/dist/data-sources/TokenDataSource.d.cts +2 -25
- package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
- package/dist/data-sources/TokenDataSource.d.mts +2 -25
- package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
- package/dist/data-sources/TokenDataSource.mjs +3 -16
- package/dist/data-sources/TokenDataSource.mjs.map +1 -1
- package/dist/data-sources/index.cjs +1 -6
- package/dist/data-sources/index.cjs.map +1 -1
- package/dist/data-sources/index.d.cts +6 -7
- package/dist/data-sources/index.d.cts.map +1 -1
- package/dist/data-sources/index.d.mts +6 -7
- package/dist/data-sources/index.d.mts.map +1 -1
- package/dist/data-sources/index.mjs +1 -3
- package/dist/data-sources/index.mjs.map +1 -1
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +11 -11
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.cjs +4 -27
- package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.cts +3 -26
- package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.mts +3 -26
- package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.mjs +4 -27
- package/dist/middlewares/DetectionMiddleware.mjs.map +1 -1
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.d.cts +1 -1
- package/dist/middlewares/index.d.cts.map +1 -1
- package/dist/middlewares/index.d.mts +1 -1
- package/dist/middlewares/index.d.mts.map +1 -1
- package/dist/middlewares/index.mjs.map +1 -1
- package/dist/selectors/balance.cjs +306 -0
- package/dist/selectors/balance.cjs.map +1 -0
- package/dist/selectors/balance.d.cts +22 -0
- package/dist/selectors/balance.d.cts.map +1 -0
- package/dist/selectors/balance.d.mts +22 -0
- package/dist/selectors/balance.d.mts.map +1 -0
- package/dist/selectors/balance.mjs +297 -0
- package/dist/selectors/balance.mjs.map +1 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +53 -18
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +53 -18
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/data-sources/initDataSources.cjs +0 -215
- package/dist/data-sources/initDataSources.cjs.map +0 -1
- package/dist/data-sources/initDataSources.d.cts +0 -140
- package/dist/data-sources/initDataSources.d.cts.map +0 -1
- package/dist/data-sources/initDataSources.d.mts +0 -140
- package/dist/data-sources/initDataSources.d.mts.map +0 -1
- package/dist/data-sources/initDataSources.mjs +0 -210
- package/dist/data-sources/initDataSources.mjs.map +0 -1
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
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");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
2
7
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
8
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
9
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
10
|
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");
|
|
6
11
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
12
|
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
-
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");
|
|
11
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_defaultUpdateInterval, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get,
|
|
16
|
+
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_defaultUpdateInterval, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_subscriptionBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_tokenDataSource, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_registerActionHandlers, _AssetsController_executeMiddlewares, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.AssetsController = exports.getDefaultAssetsControllerState = void 0;
|
|
19
19
|
const base_controller_1 = require("@metamask/base-controller");
|
|
@@ -21,12 +21,31 @@ const utils_1 = require("@metamask/utils");
|
|
|
21
21
|
const async_mutex_1 = require("async-mutex");
|
|
22
22
|
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
23
23
|
const lodash_1 = require("lodash");
|
|
24
|
+
const AccountsApiDataSource_1 = require("./data-sources/AccountsApiDataSource.cjs");
|
|
25
|
+
const BackendWebsocketDataSource_1 = require("./data-sources/BackendWebsocketDataSource.cjs");
|
|
26
|
+
const PriceDataSource_1 = require("./data-sources/PriceDataSource.cjs");
|
|
27
|
+
const RpcDataSource_1 = require("./data-sources/RpcDataSource.cjs");
|
|
28
|
+
const SnapDataSource_1 = require("./data-sources/SnapDataSource.cjs");
|
|
29
|
+
const TokenDataSource_1 = require("./data-sources/TokenDataSource.cjs");
|
|
24
30
|
const logger_1 = require("./logger.cjs");
|
|
31
|
+
const DetectionMiddleware_1 = require("./middlewares/DetectionMiddleware.cjs");
|
|
25
32
|
const utils_2 = require("./utils.cjs");
|
|
26
33
|
// ============================================================================
|
|
27
34
|
// CONTROLLER CONSTANTS
|
|
28
35
|
// ============================================================================
|
|
29
36
|
const CONTROLLER_NAME = 'AssetsController';
|
|
37
|
+
/** Method names exposed as messenger actions (AssetsController:getAssets, etc.) */
|
|
38
|
+
const MESSENGER_EXPOSED_METHODS = [
|
|
39
|
+
'getAssets',
|
|
40
|
+
'getAssetsBalance',
|
|
41
|
+
'getAssetMetadata',
|
|
42
|
+
'getAssetsPrice',
|
|
43
|
+
'addCustomAsset',
|
|
44
|
+
'removeCustomAsset',
|
|
45
|
+
'getCustomAssets',
|
|
46
|
+
'hideAsset',
|
|
47
|
+
'unhideAsset',
|
|
48
|
+
];
|
|
30
49
|
/** Default polling interval hint for data sources (30 seconds) */
|
|
31
50
|
const DEFAULT_POLLING_INTERVAL_MS = 30000;
|
|
32
51
|
const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, CONTROLLER_NAME);
|
|
@@ -153,13 +172,8 @@ function normalizeResponse(response) {
|
|
|
153
172
|
* based on which chains they support. When active chains change, the controller
|
|
154
173
|
* dynamically adjusts subscriptions.
|
|
155
174
|
*
|
|
156
|
-
* 4. **
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* ## App Lifecycle
|
|
160
|
-
*
|
|
161
|
-
* - **App Opened** (`AppStateController:appOpened`): Starts subscriptions, fetches initial data
|
|
162
|
-
* - **App Closed** (`AppStateController:appClosed`): Stops all subscriptions to conserve resources
|
|
175
|
+
* 4. **Keyring Lifecycle**: Listens to KeyringController unlock/lock events to
|
|
176
|
+
* start/stop subscriptions when the wallet is unlocked or locked.
|
|
163
177
|
*
|
|
164
178
|
* ## Architecture
|
|
165
179
|
*
|
|
@@ -168,7 +182,7 @@ function normalizeResponse(response) {
|
|
|
168
182
|
* - The controller does NOT manage polling - it simply receives pushed updates
|
|
169
183
|
*/
|
|
170
184
|
class AssetsController extends base_controller_1.BaseController {
|
|
171
|
-
constructor({ messenger, state = {}, defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS, isEnabled = () => true, }) {
|
|
185
|
+
constructor({ messenger, state = {}, defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS, isEnabled = () => true, queryApiClient, rpcDataSourceConfig, }) {
|
|
172
186
|
super({
|
|
173
187
|
name: CONTROLLER_NAME,
|
|
174
188
|
messenger,
|
|
@@ -193,79 +207,82 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
193
207
|
_AssetsController_activeSubscriptions.set(this, new Map());
|
|
194
208
|
/** Currently enabled chains from NetworkEnablementController */
|
|
195
209
|
_AssetsController_enabledChains.set(this, new Set());
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
210
|
+
_AssetsController_backendWebsocketDataSource.set(this, void 0);
|
|
211
|
+
_AssetsController_accountsApiDataSource.set(this, void 0);
|
|
212
|
+
_AssetsController_snapDataSource.set(this, void 0);
|
|
213
|
+
_AssetsController_rpcDataSource.set(this, void 0);
|
|
214
|
+
_AssetsController_priceDataSource.set(this, void 0);
|
|
215
|
+
_AssetsController_detectionMiddleware.set(this, void 0);
|
|
216
|
+
_AssetsController_tokenDataSource.set(this, void 0);
|
|
202
217
|
__classPrivateFieldSet(this, _AssetsController_isEnabled, isEnabled(), "f");
|
|
203
218
|
__classPrivateFieldSet(this, _AssetsController_defaultUpdateInterval, defaultUpdateInterval, "f");
|
|
219
|
+
const rpcConfig = rpcDataSourceConfig ?? {};
|
|
220
|
+
const onActiveChainsUpdated = (dataSourceName, chains, previousChains) => this.handleActiveChainsUpdate(dataSourceName, chains, previousChains);
|
|
221
|
+
__classPrivateFieldSet(this, _AssetsController_backendWebsocketDataSource, new BackendWebsocketDataSource_1.BackendWebsocketDataSource({
|
|
222
|
+
messenger: this.messenger,
|
|
223
|
+
queryApiClient,
|
|
224
|
+
onActiveChainsUpdated,
|
|
225
|
+
}), "f");
|
|
226
|
+
__classPrivateFieldSet(this, _AssetsController_accountsApiDataSource, new AccountsApiDataSource_1.AccountsApiDataSource({
|
|
227
|
+
queryApiClient,
|
|
228
|
+
onActiveChainsUpdated,
|
|
229
|
+
}), "f");
|
|
230
|
+
__classPrivateFieldSet(this, _AssetsController_snapDataSource, new SnapDataSource_1.SnapDataSource({
|
|
231
|
+
messenger: this.messenger,
|
|
232
|
+
onActiveChainsUpdated,
|
|
233
|
+
}), "f");
|
|
234
|
+
__classPrivateFieldSet(this, _AssetsController_rpcDataSource, new RpcDataSource_1.RpcDataSource({
|
|
235
|
+
messenger: this.messenger,
|
|
236
|
+
onActiveChainsUpdated,
|
|
237
|
+
...rpcConfig,
|
|
238
|
+
}), "f");
|
|
239
|
+
__classPrivateFieldSet(this, _AssetsController_tokenDataSource, new TokenDataSource_1.TokenDataSource({
|
|
240
|
+
queryApiClient,
|
|
241
|
+
}), "f");
|
|
242
|
+
__classPrivateFieldSet(this, _AssetsController_priceDataSource, new PriceDataSource_1.PriceDataSource({
|
|
243
|
+
queryApiClient,
|
|
244
|
+
}), "f");
|
|
245
|
+
__classPrivateFieldSet(this, _AssetsController_detectionMiddleware, new DetectionMiddleware_1.DetectionMiddleware(), "f");
|
|
204
246
|
if (!__classPrivateFieldGet(this, _AssetsController_isEnabled, "f")) {
|
|
205
247
|
log('AssetsController is disabled, skipping initialization');
|
|
206
248
|
return;
|
|
207
249
|
}
|
|
208
250
|
log('Initializing AssetsController', {
|
|
209
|
-
defaultUpdateInterval,
|
|
251
|
+
defaultUpdateInterval: __classPrivateFieldGet(this, _AssetsController_defaultUpdateInterval, "f"),
|
|
210
252
|
});
|
|
211
253
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_initializeState).call(this);
|
|
212
254
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeToEvents).call(this);
|
|
213
255
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_registerActionHandlers).call(this);
|
|
214
|
-
// Register data sources (order = subscription priority)
|
|
215
|
-
this.registerDataSources([
|
|
216
|
-
'BackendWebsocketDataSource', // Real-time push updates
|
|
217
|
-
'AccountsApiDataSource', // HTTP polling fallback
|
|
218
|
-
'SnapDataSource', // Solana/Bitcoin/Tron snaps
|
|
219
|
-
'RpcDataSource', // Direct blockchain queries
|
|
220
|
-
]);
|
|
221
|
-
}
|
|
222
|
-
// ============================================================================
|
|
223
|
-
// DATA SOURCE MANAGEMENT
|
|
224
|
-
// ============================================================================
|
|
225
|
-
/**
|
|
226
|
-
* Register data sources with the controller.
|
|
227
|
-
* Order of the array determines subscription order.
|
|
228
|
-
*
|
|
229
|
-
* Data sources report chain changes by calling `AssetsController:activeChainsUpdate` action.
|
|
230
|
-
*
|
|
231
|
-
* @param dataSourceIds - Array of data source identifiers to register.
|
|
232
|
-
*/
|
|
233
|
-
registerDataSources(dataSourceIds) {
|
|
234
|
-
for (const id of dataSourceIds) {
|
|
235
|
-
log('Registering data source', { id });
|
|
236
|
-
// Initialize available chains tracking for this source
|
|
237
|
-
__classPrivateFieldGet(this, _AssetsController_dataSources, "f").set(id, new Set());
|
|
238
|
-
}
|
|
239
256
|
}
|
|
240
257
|
// ============================================================================
|
|
241
258
|
// DATA SOURCE CHAIN MANAGEMENT
|
|
242
259
|
// ============================================================================
|
|
243
260
|
/**
|
|
244
|
-
* Handle when a data source's
|
|
245
|
-
*
|
|
246
|
-
*
|
|
261
|
+
* Handle when a data source's supported chains change.
|
|
262
|
+
* Used to refresh balance subscriptions and run a one-time fetch when a new chain is supported.
|
|
263
|
+
*
|
|
264
|
+
* - On any add/remove: re-subscribes to data sources so chain assignment stays correct.
|
|
265
|
+
* - When chains are added: fetches balances for the new chains (for selected accounts on enabled networks).
|
|
247
266
|
*
|
|
248
|
-
*
|
|
267
|
+
* Controller does not store chains; sources report via this callback. previousChains is required for diff.
|
|
249
268
|
*
|
|
250
269
|
* @param dataSourceId - The identifier of the data source reporting the change.
|
|
251
|
-
* @param activeChains -
|
|
270
|
+
* @param activeChains - Currently active (supported and available) chain IDs for this source.
|
|
271
|
+
* @param previousChains - Previous chains; used to compute added/removed.
|
|
252
272
|
*/
|
|
253
|
-
handleActiveChainsUpdate(dataSourceId, activeChains) {
|
|
273
|
+
handleActiveChainsUpdate(dataSourceId, activeChains, previousChains) {
|
|
254
274
|
log('Data source active chains changed', {
|
|
255
275
|
dataSourceId,
|
|
256
276
|
chainCount: activeChains.length,
|
|
257
277
|
chains: activeChains,
|
|
258
278
|
});
|
|
259
|
-
const
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// Check for changes
|
|
264
|
-
const addedChains = activeChains.filter((chain) => !previousChains.has(chain));
|
|
265
|
-
const removedChains = Array.from(previousChains).filter((chain) => !newChains.has(chain));
|
|
279
|
+
const previous = previousChains;
|
|
280
|
+
const previousSet = new Set(previous);
|
|
281
|
+
const addedChains = activeChains.filter((ch) => !previousSet.has(ch));
|
|
282
|
+
const removedChains = previous.filter((ch) => !activeChains.includes(ch));
|
|
266
283
|
if (addedChains.length > 0 || removedChains.length > 0) {
|
|
267
284
|
// Refresh subscriptions to use updated data source availability
|
|
268
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
285
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
269
286
|
}
|
|
270
287
|
// If chains were added and we have selected accounts, do one-time fetch
|
|
271
288
|
if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
|
|
@@ -295,21 +312,20 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
295
312
|
customAssets.push(...accountCustomAssets);
|
|
296
313
|
}
|
|
297
314
|
if (options?.forceUpdate) {
|
|
298
|
-
const
|
|
299
|
-
this.messenger.call('AccountsApiDataSource:getAssetsMiddleware'),
|
|
300
|
-
this.messenger.call('SnapDataSource:getAssetsMiddleware'),
|
|
301
|
-
this.messenger.call('RpcDataSource:getAssetsMiddleware'),
|
|
302
|
-
this.messenger.call('DetectionMiddleware:getAssetsMiddleware'),
|
|
303
|
-
this.messenger.call('TokenDataSource:getAssetsMiddleware'),
|
|
304
|
-
this.messenger.call('PriceDataSource:getAssetsMiddleware'),
|
|
305
|
-
], {
|
|
306
|
-
accounts,
|
|
307
|
-
chainIds,
|
|
315
|
+
const request = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
|
|
308
316
|
assetTypes,
|
|
309
317
|
dataTypes,
|
|
310
318
|
customAssets: customAssets.length > 0 ? customAssets : undefined,
|
|
311
319
|
forceUpdate: true,
|
|
312
320
|
});
|
|
321
|
+
const response = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, [
|
|
322
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f").assetsMiddleware,
|
|
323
|
+
__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f").assetsMiddleware,
|
|
324
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f").assetsMiddleware,
|
|
325
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f").assetsMiddleware,
|
|
326
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f").assetsMiddleware,
|
|
327
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").assetsMiddleware,
|
|
328
|
+
], request);
|
|
313
329
|
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, response);
|
|
314
330
|
}
|
|
315
331
|
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetsFromState).call(this, accounts, chainIds, assetTypes);
|
|
@@ -463,6 +479,9 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
463
479
|
}
|
|
464
480
|
});
|
|
465
481
|
}
|
|
482
|
+
// ============================================================================
|
|
483
|
+
// SUBSCRIPTIONS
|
|
484
|
+
// ============================================================================
|
|
466
485
|
/**
|
|
467
486
|
* Subscribe to price updates for all assets held by the given accounts.
|
|
468
487
|
* Polls PriceDataSource which fetches prices from balance state.
|
|
@@ -477,19 +496,17 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
477
496
|
const subscriptionKey = 'ds:PriceDataSource';
|
|
478
497
|
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
479
498
|
const isUpdate = existingSubscription !== undefined;
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
.call('PriceDataSource:subscribe', {
|
|
483
|
-
request: {
|
|
484
|
-
accounts,
|
|
485
|
-
chainIds,
|
|
499
|
+
const subscribeReq = {
|
|
500
|
+
request: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
|
|
486
501
|
dataTypes: ['price'],
|
|
487
502
|
updateInterval,
|
|
488
|
-
},
|
|
503
|
+
}),
|
|
489
504
|
subscriptionId: subscriptionKey,
|
|
490
505
|
isUpdate,
|
|
491
|
-
|
|
492
|
-
|
|
506
|
+
onAssetsUpdate: (response) => this.handleAssetsUpdate(response, 'PriceDataSource'),
|
|
507
|
+
getAssetsState: () => this.state,
|
|
508
|
+
};
|
|
509
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").subscribe(subscribeReq).catch(console.error);
|
|
493
510
|
// Track subscription
|
|
494
511
|
const subscription = {
|
|
495
512
|
chains: chainIds,
|
|
@@ -511,37 +528,55 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
511
528
|
if (!existingSubscription) {
|
|
512
529
|
return;
|
|
513
530
|
}
|
|
514
|
-
|
|
515
|
-
this.messenger
|
|
516
|
-
.call('PriceDataSource:unsubscribe', subscriptionKey)
|
|
517
|
-
.catch(console.error);
|
|
531
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").unsubscribe(subscriptionKey).catch(console.error);
|
|
518
532
|
existingSubscription.unsubscribe();
|
|
519
533
|
}
|
|
520
534
|
/**
|
|
521
535
|
* Handle assets updated from a data source.
|
|
522
|
-
* Called via
|
|
536
|
+
* Called via the onAssetsUpdate callback passed in SubscriptionRequest when the controller subscribes to a data source.
|
|
537
|
+
* Enriches the response with token metadata (via middlewares) before updating state.
|
|
523
538
|
*
|
|
524
539
|
* @param response - The data response with updated assets
|
|
525
540
|
* @param sourceId - The data source ID reporting the update
|
|
541
|
+
* @param request - Optional original request for context when enriching
|
|
526
542
|
*/
|
|
527
|
-
async handleAssetsUpdate(response, sourceId) {
|
|
543
|
+
async handleAssetsUpdate(response, sourceId, request) {
|
|
528
544
|
log('Assets updated from data source', {
|
|
529
545
|
sourceId,
|
|
530
546
|
hasBalance: Boolean(response.assetsBalance),
|
|
531
547
|
hasPrice: Boolean(response.assetsPrice),
|
|
532
548
|
});
|
|
533
|
-
|
|
549
|
+
// Run through enrichment middlewares (Event Stack: Detection → Token → Price)
|
|
550
|
+
// Include 'metadata' in dataTypes so TokenDataSource runs to enrich detected assets
|
|
551
|
+
const enrichedResponse = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, [
|
|
552
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f").assetsMiddleware,
|
|
553
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f").assetsMiddleware,
|
|
554
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").assetsMiddleware,
|
|
555
|
+
], request ?? {
|
|
556
|
+
accountsWithSupportedChains: [],
|
|
557
|
+
chainIds: [],
|
|
558
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
559
|
+
}, response);
|
|
560
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, enrichedResponse);
|
|
534
561
|
}
|
|
535
562
|
// ============================================================================
|
|
536
563
|
// CLEANUP
|
|
537
564
|
// ============================================================================
|
|
538
565
|
destroy() {
|
|
539
566
|
log('Destroying AssetsController', {
|
|
540
|
-
dataSourceCount: __classPrivateFieldGet(this,
|
|
567
|
+
dataSourceCount: __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_subscriptionBalanceDataSources_get).length,
|
|
541
568
|
subscriptionCount: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size,
|
|
542
569
|
});
|
|
543
|
-
//
|
|
544
|
-
__classPrivateFieldGet(this,
|
|
570
|
+
// Destroy instantiated data sources
|
|
571
|
+
__classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f")?.destroy?.();
|
|
572
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f")?.destroy?.();
|
|
573
|
+
__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f")?.destroy?.();
|
|
574
|
+
if (__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f") &&
|
|
575
|
+
'destroy' in __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f") &&
|
|
576
|
+
typeof __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f").destroy ===
|
|
577
|
+
'function') {
|
|
578
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f").destroy();
|
|
579
|
+
}
|
|
545
580
|
// Stop all active subscriptions
|
|
546
581
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this);
|
|
547
582
|
// Unregister action handlers
|
|
@@ -549,8 +584,6 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
549
584
|
this.messenger.unregisterActionHandler('AssetsController:getAssetsBalance');
|
|
550
585
|
this.messenger.unregisterActionHandler('AssetsController:getAssetMetadata');
|
|
551
586
|
this.messenger.unregisterActionHandler('AssetsController:getAssetsPrice');
|
|
552
|
-
this.messenger.unregisterActionHandler('AssetsController:activeChainsUpdate');
|
|
553
|
-
this.messenger.unregisterActionHandler('AssetsController:assetsUpdate');
|
|
554
587
|
this.messenger.unregisterActionHandler('AssetsController:addCustomAsset');
|
|
555
588
|
this.messenger.unregisterActionHandler('AssetsController:removeCustomAsset');
|
|
556
589
|
this.messenger.unregisterActionHandler('AssetsController:getCustomAssets');
|
|
@@ -559,8 +592,15 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
559
592
|
}
|
|
560
593
|
}
|
|
561
594
|
exports.AssetsController = AssetsController;
|
|
562
|
-
_AssetsController_isEnabled = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(),
|
|
595
|
+
_AssetsController_isEnabled = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_backendWebsocketDataSource = new WeakMap(), _AssetsController_accountsApiDataSource = new WeakMap(), _AssetsController_snapDataSource = new WeakMap(), _AssetsController_rpcDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_selectedAccounts_get = function _AssetsController_selectedAccounts_get() {
|
|
563
596
|
return this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup');
|
|
597
|
+
}, _AssetsController_subscriptionBalanceDataSources_get = function _AssetsController_subscriptionBalanceDataSources_get() {
|
|
598
|
+
return [
|
|
599
|
+
__classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f"),
|
|
600
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
|
|
601
|
+
__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"),
|
|
602
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f"),
|
|
603
|
+
];
|
|
564
604
|
}, _AssetsController_initializeState = function _AssetsController_initializeState() {
|
|
565
605
|
const { enabledNetworkMap } = this.messenger.call('NetworkEnablementController:getState');
|
|
566
606
|
__classPrivateFieldSet(this, _AssetsController_enabledChains, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_extractEnabledChains).call(this, enabledNetworkMap), "f");
|
|
@@ -602,24 +642,11 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_defaultUpdateInte
|
|
|
602
642
|
this.messenger.subscribe('NetworkEnablementController:stateChange', ({ enabledNetworkMap }) => {
|
|
603
643
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleEnabledNetworksChanged).call(this, enabledNetworkMap).catch(console.error);
|
|
604
644
|
});
|
|
605
|
-
// App lifecycle: start when opened, stop when closed
|
|
606
|
-
this.messenger.subscribe('AppStateController:appOpened', () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_start).call(this));
|
|
607
|
-
this.messenger.subscribe('AppStateController:appClosed', () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this));
|
|
608
645
|
// Keyring lifecycle: start when unlocked, stop when locked
|
|
609
646
|
this.messenger.subscribe('KeyringController:unlock', () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_start).call(this));
|
|
610
647
|
this.messenger.subscribe('KeyringController:lock', () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this));
|
|
611
648
|
}, _AssetsController_registerActionHandlers = function _AssetsController_registerActionHandlers() {
|
|
612
|
-
this.messenger.
|
|
613
|
-
this.messenger.registerActionHandler('AssetsController:getAssetsBalance', this.getAssetsBalance.bind(this));
|
|
614
|
-
this.messenger.registerActionHandler('AssetsController:getAssetMetadata', this.getAssetMetadata.bind(this));
|
|
615
|
-
this.messenger.registerActionHandler('AssetsController:getAssetsPrice', this.getAssetsPrice.bind(this));
|
|
616
|
-
this.messenger.registerActionHandler('AssetsController:activeChainsUpdate', this.handleActiveChainsUpdate.bind(this));
|
|
617
|
-
this.messenger.registerActionHandler('AssetsController:assetsUpdate', this.handleAssetsUpdate.bind(this));
|
|
618
|
-
this.messenger.registerActionHandler('AssetsController:addCustomAsset', this.addCustomAsset.bind(this));
|
|
619
|
-
this.messenger.registerActionHandler('AssetsController:removeCustomAsset', this.removeCustomAsset.bind(this));
|
|
620
|
-
this.messenger.registerActionHandler('AssetsController:getCustomAssets', this.getCustomAssets.bind(this));
|
|
621
|
-
this.messenger.registerActionHandler('AssetsController:hideAsset', this.hideAsset.bind(this));
|
|
622
|
-
this.messenger.registerActionHandler('AssetsController:unhideAsset', this.unhideAsset.bind(this));
|
|
649
|
+
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
623
650
|
}, _AssetsController_executeMiddlewares =
|
|
624
651
|
// ============================================================================
|
|
625
652
|
// MIDDLEWARE EXECUTION
|
|
@@ -648,32 +675,6 @@ async function _AssetsController_executeMiddlewares(middlewares, request, initia
|
|
|
648
675
|
getAssetsState: () => this.state,
|
|
649
676
|
});
|
|
650
677
|
return result.response;
|
|
651
|
-
}, _AssetsController_assignChainsToDataSources = function _AssetsController_assignChainsToDataSources(requestedChains) {
|
|
652
|
-
const assignment = new Map();
|
|
653
|
-
const remainingChains = new Set(requestedChains);
|
|
654
|
-
for (const sourceId of __classPrivateFieldGet(this, _AssetsController_dataSources, "f").keys()) {
|
|
655
|
-
// Get available chains for this data source
|
|
656
|
-
const availableChains = __classPrivateFieldGet(this, _AssetsController_dataSources, "f").get(sourceId);
|
|
657
|
-
if (!availableChains || availableChains.size === 0) {
|
|
658
|
-
continue;
|
|
659
|
-
}
|
|
660
|
-
const chainsForThisSource = [];
|
|
661
|
-
for (const chainId of remainingChains) {
|
|
662
|
-
// Check if this chain is available on this source
|
|
663
|
-
if (availableChains.has(chainId)) {
|
|
664
|
-
chainsForThisSource.push(chainId);
|
|
665
|
-
remainingChains.delete(chainId);
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
if (chainsForThisSource.length > 0) {
|
|
669
|
-
assignment.set(sourceId, chainsForThisSource);
|
|
670
|
-
log('Assigned chains to data source', {
|
|
671
|
-
sourceId,
|
|
672
|
-
chains: chainsForThisSource,
|
|
673
|
-
});
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
return assignment;
|
|
677
678
|
}, _AssetsController_updateState =
|
|
678
679
|
// ============================================================================
|
|
679
680
|
// STATE MANAGEMENT
|
|
@@ -867,7 +868,7 @@ async function _AssetsController_updateState(response) {
|
|
|
867
868
|
selectedAccountCount: __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length,
|
|
868
869
|
enabledChainCount: __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").size,
|
|
869
870
|
});
|
|
870
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
871
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
871
872
|
if (__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
|
|
872
873
|
this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {
|
|
873
874
|
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
@@ -888,77 +889,67 @@ async function _AssetsController_updateState(response) {
|
|
|
888
889
|
// Convert to array first to avoid modifying map during iteration
|
|
889
890
|
const subscriptionKeys = [...__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").keys()];
|
|
890
891
|
for (const subscriptionKey of subscriptionKeys) {
|
|
891
|
-
// Extract sourceId from subscription key (format: "ds:${sourceId}")
|
|
892
892
|
if (subscriptionKey.startsWith('ds:')) {
|
|
893
893
|
const sourceId = subscriptionKey.slice(3);
|
|
894
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "
|
|
894
|
+
const source = __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_subscriptionBalanceDataSources_get).find((ds) => ds.getName() === sourceId);
|
|
895
|
+
if (source) {
|
|
896
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
|
|
897
|
+
}
|
|
895
898
|
}
|
|
896
899
|
}
|
|
897
900
|
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").clear();
|
|
898
|
-
},
|
|
901
|
+
}, _AssetsController_subscribeAssets = function _AssetsController_subscribeAssets() {
|
|
899
902
|
if (__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length === 0) {
|
|
900
903
|
return;
|
|
901
904
|
}
|
|
902
905
|
// Subscribe to balance updates (batched by data source)
|
|
903
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this)
|
|
906
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [
|
|
907
|
+
...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f"),
|
|
908
|
+
]);
|
|
904
909
|
// Subscribe to price updates for all assets held by selected accounts
|
|
905
910
|
this.subscribeAssetsPrice(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
|
|
906
|
-
}, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance() {
|
|
907
|
-
|
|
908
|
-
const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), __classPrivateFieldGet(this, _AssetsController_enabledChains, "f"));
|
|
909
|
-
// Step 2: Split by data source active chains (ordered by priority)
|
|
910
|
-
// Get all chains that need to be subscribed
|
|
911
|
+
}, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance(accounts, chainIds) {
|
|
912
|
+
const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, accounts, new Set(chainIds));
|
|
911
913
|
const remainingChains = new Set(chainToAccounts.keys());
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
const assignedChains = chainAssignment.get(sourceId);
|
|
921
|
-
if (!assignedChains || assignedChains.length === 0) {
|
|
922
|
-
// Unsubscribe from data sources with no assigned chains
|
|
923
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, sourceId);
|
|
924
|
-
continue;
|
|
914
|
+
for (const source of __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_subscriptionBalanceDataSources_get)) {
|
|
915
|
+
const availableChains = new Set(source.getActiveChainsSync());
|
|
916
|
+
const assignedChains = [];
|
|
917
|
+
for (const chainId of remainingChains) {
|
|
918
|
+
if (availableChains.has(chainId)) {
|
|
919
|
+
assignedChains.push(chainId);
|
|
920
|
+
remainingChains.delete(chainId);
|
|
921
|
+
}
|
|
925
922
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
if (accountsForSource.length === 0) {
|
|
923
|
+
if (assignedChains.length === 0) {
|
|
924
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
|
|
929
925
|
continue;
|
|
930
926
|
}
|
|
931
|
-
|
|
932
|
-
|
|
927
|
+
const seenIds = new Set();
|
|
928
|
+
const accountsForSource = assignedChains
|
|
929
|
+
.flatMap((chainId) => chainToAccounts.get(chainId) ?? [])
|
|
930
|
+
.filter((account) => !seenIds.has(account.id) && (seenIds.add(account.id), true));
|
|
931
|
+
if (accountsForSource.length > 0) {
|
|
932
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accountsForSource, assignedChains);
|
|
933
|
+
}
|
|
933
934
|
}
|
|
934
935
|
}, _AssetsController_buildChainToAccountsMap = function _AssetsController_buildChainToAccountsMap(accounts, chainsToSubscribe) {
|
|
935
936
|
const chainToAccounts = new Map();
|
|
936
937
|
for (const account of accounts) {
|
|
937
|
-
const
|
|
938
|
-
for (const chainId of accountChains) {
|
|
938
|
+
for (const chainId of __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account)) {
|
|
939
939
|
if (!chainsToSubscribe.has(chainId)) {
|
|
940
940
|
continue;
|
|
941
941
|
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
}
|
|
947
|
-
return chainToAccounts;
|
|
948
|
-
}, _AssetsController_getAccountsForChains = function _AssetsController_getAccountsForChains(chains, chainToAccounts) {
|
|
949
|
-
const accountIds = new Set();
|
|
950
|
-
const accounts = [];
|
|
951
|
-
for (const chainId of chains) {
|
|
952
|
-
const chainAccounts = chainToAccounts.get(chainId) ?? [];
|
|
953
|
-
for (const account of chainAccounts) {
|
|
954
|
-
if (!accountIds.has(account.id)) {
|
|
955
|
-
accountIds.add(account.id);
|
|
956
|
-
accounts.push(account);
|
|
942
|
+
let list = chainToAccounts.get(chainId);
|
|
943
|
+
if (!list) {
|
|
944
|
+
list = [];
|
|
945
|
+
chainToAccounts.set(chainId, list);
|
|
957
946
|
}
|
|
947
|
+
list.push(account);
|
|
958
948
|
}
|
|
959
949
|
}
|
|
960
|
-
return
|
|
961
|
-
},
|
|
950
|
+
return chainToAccounts;
|
|
951
|
+
}, _AssetsController_subscribeDataSource = function _AssetsController_subscribeDataSource(source, accounts, chains) {
|
|
952
|
+
const sourceId = source.getName();
|
|
962
953
|
const subscriptionKey = `ds:${sourceId}`;
|
|
963
954
|
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
964
955
|
const isUpdate = existingSubscription !== undefined;
|
|
@@ -969,53 +960,49 @@ async function _AssetsController_updateState(response) {
|
|
|
969
960
|
accountCount: accounts.length,
|
|
970
961
|
chainCount: chains.length,
|
|
971
962
|
});
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
}
|
|
987
|
-
catch (error) {
|
|
988
|
-
console.error(`[AssetsController] Failed to subscribe to '${sourceId}':`, error);
|
|
989
|
-
}
|
|
990
|
-
})().catch(console.error);
|
|
963
|
+
const subscribeReq = {
|
|
964
|
+
request: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chains, {
|
|
965
|
+
assetTypes: ['fungible'],
|
|
966
|
+
dataTypes: ['balance'],
|
|
967
|
+
updateInterval: __classPrivateFieldGet(this, _AssetsController_defaultUpdateInterval, "f"),
|
|
968
|
+
}),
|
|
969
|
+
subscriptionId: subscriptionKey,
|
|
970
|
+
isUpdate,
|
|
971
|
+
onAssetsUpdate: (response) => this.handleAssetsUpdate(response, sourceId),
|
|
972
|
+
getAssetsState: () => this.state,
|
|
973
|
+
};
|
|
974
|
+
source.subscribe(subscribeReq).catch((error) => {
|
|
975
|
+
console.error(`[AssetsController] Failed to subscribe to '${sourceId}':`, error);
|
|
976
|
+
});
|
|
991
977
|
// Track subscription
|
|
992
978
|
const subscription = {
|
|
993
979
|
chains,
|
|
994
980
|
accountId: subscriptionKey,
|
|
995
981
|
assetTypes: ['fungible'],
|
|
996
|
-
dataTypes: ['balance'
|
|
982
|
+
dataTypes: ['balance'],
|
|
997
983
|
unsubscribe: () => {
|
|
998
984
|
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").delete(subscriptionKey);
|
|
999
985
|
},
|
|
1000
986
|
};
|
|
1001
987
|
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").set(subscriptionKey, subscription);
|
|
1002
|
-
}, _AssetsController_unsubscribeDataSource = function _AssetsController_unsubscribeDataSource(
|
|
1003
|
-
const subscriptionKey = `ds:${
|
|
988
|
+
}, _AssetsController_unsubscribeDataSource = function _AssetsController_unsubscribeDataSource(source) {
|
|
989
|
+
const subscriptionKey = `ds:${source.getName()}`;
|
|
1004
990
|
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
1005
991
|
if (existingSubscription) {
|
|
1006
|
-
|
|
1007
|
-
(async () => {
|
|
1008
|
-
try {
|
|
1009
|
-
await this.messenger.call(`${sourceId}:unsubscribe`, subscriptionKey);
|
|
1010
|
-
}
|
|
1011
|
-
catch {
|
|
1012
|
-
// Ignore errors - source may not have been subscribed
|
|
1013
|
-
}
|
|
1014
|
-
})().catch(() => {
|
|
1015
|
-
// Ignore errors - source may not have been subscribed
|
|
1016
|
-
});
|
|
992
|
+
source.unsubscribe(subscriptionKey).catch(() => undefined);
|
|
1017
993
|
existingSubscription.unsubscribe();
|
|
1018
994
|
}
|
|
995
|
+
}, _AssetsController_buildDataRequest = function _AssetsController_buildDataRequest(accounts, chainIds, partial = {}) {
|
|
996
|
+
const chainIdSet = new Set(chainIds);
|
|
997
|
+
const accountsWithSupportedChains = accounts.map((account) => ({
|
|
998
|
+
account,
|
|
999
|
+
supportedChains: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account).filter((chain) => chainIdSet.has(chain)),
|
|
1000
|
+
}));
|
|
1001
|
+
return {
|
|
1002
|
+
accountsWithSupportedChains,
|
|
1003
|
+
chainIds,
|
|
1004
|
+
...partial,
|
|
1005
|
+
};
|
|
1019
1006
|
}, _AssetsController_getEnabledChainsForAccount = function _AssetsController_getEnabledChainsForAccount(account) {
|
|
1020
1007
|
// Account scopes are CAIP-2 chain IDs like "eip155:1", "solana:mainnet", "bip122:..."
|
|
1021
1008
|
const scopes = account.scopes ?? [];
|
|
@@ -1050,7 +1037,7 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
1050
1037
|
accountIds: accounts.map((a) => a.id),
|
|
1051
1038
|
});
|
|
1052
1039
|
// Subscribe and fetch for the new account group
|
|
1053
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
1040
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1054
1041
|
if (accounts.length > 0) {
|
|
1055
1042
|
await this.getAssets(accounts, {
|
|
1056
1043
|
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
@@ -1084,7 +1071,7 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
1084
1071
|
// Users may want to see historical balances even if the network is currently disabled.
|
|
1085
1072
|
// The data will simply not be updated until the network is re-enabled.
|
|
1086
1073
|
// Refresh subscriptions for new chain set
|
|
1087
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
1074
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1088
1075
|
// Do one-time fetch for newly enabled chains
|
|
1089
1076
|
if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
|
|
1090
1077
|
await this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {
|
|
@@ -1092,28 +1079,5 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
1092
1079
|
forceUpdate: true,
|
|
1093
1080
|
});
|
|
1094
1081
|
}
|
|
1095
|
-
}, _AssetsController_handleSubscriptionUpdate =
|
|
1096
|
-
/**
|
|
1097
|
-
* Handle an async update from a data source subscription.
|
|
1098
|
-
* Enriches response with token metadata before updating state.
|
|
1099
|
-
*
|
|
1100
|
-
* @param response - The data response from the data source.
|
|
1101
|
-
* @param _sourceId - The source ID (unused but kept for logging context).
|
|
1102
|
-
* @param request - Optional original request for context.
|
|
1103
|
-
*/
|
|
1104
|
-
async function _AssetsController_handleSubscriptionUpdate(response, _sourceId, request) {
|
|
1105
|
-
// Run through enrichment middlewares (Event Stack: Detection → Token → Price)
|
|
1106
|
-
// Include 'metadata' in dataTypes so TokenDataSource runs to enrich detected assets
|
|
1107
|
-
const enrichedResponse = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, [
|
|
1108
|
-
this.messenger.call('DetectionMiddleware:getAssetsMiddleware'),
|
|
1109
|
-
this.messenger.call('TokenDataSource:getAssetsMiddleware'),
|
|
1110
|
-
this.messenger.call('PriceDataSource:getAssetsMiddleware'),
|
|
1111
|
-
], request ?? {
|
|
1112
|
-
accounts: [],
|
|
1113
|
-
chainIds: [],
|
|
1114
|
-
dataTypes: ['balance', 'metadata', 'price'],
|
|
1115
|
-
}, response);
|
|
1116
|
-
// Update state
|
|
1117
|
-
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, enrichedResponse);
|
|
1118
1082
|
};
|
|
1119
1083
|
//# sourceMappingURL=AssetsController.cjs.map
|