@metamask/assets-controller 0.2.0 → 2.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 +39 -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 +346 -271
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts +92 -96
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts +92 -96
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +347 -272
- 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 +92 -111
- package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.cts +27 -70
- package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.mts +27 -70
- package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.mjs +88 -107
- package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.cjs +141 -46
- 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 +141 -46
- package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
- package/dist/data-sources/PriceDataSource.cjs +39 -48
- package/dist/data-sources/PriceDataSource.cjs.map +1 -1
- package/dist/data-sources/PriceDataSource.d.cts +13 -92
- package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
- package/dist/data-sources/PriceDataSource.d.mts +13 -92
- package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
- package/dist/data-sources/PriceDataSource.mjs +39 -48
- package/dist/data-sources/PriceDataSource.mjs.map +1 -1
- package/dist/data-sources/RpcDataSource.cjs +184 -142
- package/dist/data-sources/RpcDataSource.cjs.map +1 -1
- package/dist/data-sources/RpcDataSource.d.cts +29 -114
- package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
- package/dist/data-sources/RpcDataSource.d.mts +29 -114
- package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
- package/dist/data-sources/RpcDataSource.mjs +185 -143
- package/dist/data-sources/RpcDataSource.mjs.map +1 -1
- package/dist/data-sources/SnapDataSource.cjs +53 -39
- package/dist/data-sources/SnapDataSource.cjs.map +1 -1
- package/dist/data-sources/SnapDataSource.d.cts +9 -45
- package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
- package/dist/data-sources/SnapDataSource.d.mts +9 -45
- package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
- package/dist/data-sources/SnapDataSource.mjs +53 -39
- package/dist/data-sources/SnapDataSource.mjs.map +1 -1
- package/dist/data-sources/StakedBalanceDataSource.cjs +609 -0
- package/dist/data-sources/StakedBalanceDataSource.cjs.map +1 -0
- package/dist/data-sources/StakedBalanceDataSource.d.cts +72 -0
- package/dist/data-sources/StakedBalanceDataSource.d.cts.map +1 -0
- package/dist/data-sources/StakedBalanceDataSource.d.mts +72 -0
- package/dist/data-sources/StakedBalanceDataSource.d.mts.map +1 -0
- package/dist/data-sources/StakedBalanceDataSource.mjs +605 -0
- package/dist/data-sources/StakedBalanceDataSource.mjs.map +1 -0
- package/dist/data-sources/TokenDataSource.cjs +15 -21
- package/dist/data-sources/TokenDataSource.cjs.map +1 -1
- package/dist/data-sources/TokenDataSource.d.cts +3 -25
- package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
- package/dist/data-sources/TokenDataSource.d.mts +3 -25
- package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
- package/dist/data-sources/TokenDataSource.mjs +15 -21
- package/dist/data-sources/TokenDataSource.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/index.cjs +5 -1
- package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/index.d.cts +1 -1
- package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/index.d.mts +1 -1
- package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/index.mjs +1 -1
- package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs +132 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts +78 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts +78 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs +126 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs +16 -0
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts +5 -1
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts +5 -1
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs +16 -0
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/index.cjs +6 -1
- package/dist/data-sources/evm-rpc-services/services/index.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/index.d.cts +1 -0
- package/dist/data-sources/evm-rpc-services/services/index.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/index.d.mts +1 -0
- package/dist/data-sources/evm-rpc-services/services/index.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/index.mjs +1 -0
- package/dist/data-sources/evm-rpc-services/services/index.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/services.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/services.d.cts +4 -0
- package/dist/data-sources/evm-rpc-services/types/services.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/services.d.mts +4 -0
- package/dist/data-sources/evm-rpc-services/types/services.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/services.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/state.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/state.d.cts +3 -3
- package/dist/data-sources/evm-rpc-services/types/state.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/state.d.mts +3 -3
- package/dist/data-sources/evm-rpc-services/types/state.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/state.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/utils/index.cjs +9 -1
- package/dist/data-sources/evm-rpc-services/utils/index.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/utils/index.d.cts +2 -0
- package/dist/data-sources/evm-rpc-services/utils/index.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/utils/index.d.mts +2 -0
- package/dist/data-sources/evm-rpc-services/utils/index.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/utils/index.mjs +2 -0
- package/dist/data-sources/evm-rpc-services/utils/index.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/utils/parsing.cjs +47 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts +25 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts +25 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.mjs +39 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs +68 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts +25 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts +25 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs +62 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs.map +1 -0
- package/dist/data-sources/index.cjs +3 -6
- package/dist/data-sources/index.cjs.map +1 -1
- package/dist/data-sources/index.d.cts +7 -7
- package/dist/data-sources/index.d.cts.map +1 -1
- package/dist/data-sources/index.d.mts +7 -7
- package/dist/data-sources/index.d.mts.map +1 -1
- package/dist/data-sources/index.mjs +2 -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 +8 -28
- package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.cts +4 -26
- package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.mts +4 -26
- package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.mjs +8 -28
- 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 +56 -21
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +56 -21
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +13 -10
- 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,27 +1,47 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
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
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
1
6
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
7
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
8
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
9
|
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");
|
|
5
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
11
|
};
|
|
7
|
-
var
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
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");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_defaultUpdateInterval, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get, _AssetsController_dataSources, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_registerActionHandlers, _AssetsController_executeMiddlewares, _AssetsController_assignChainsToDataSources, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeToDataSources, _AssetsController_subscribeAssetsBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_getAccountsForChains, _AssetsController_subscribeToDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged, _AssetsController_handleSubscriptionUpdate;
|
|
12
|
+
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trackMetaMetricsEvent, _AssetsController_firstInitFetchReported, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _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_subscribeStakedBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
|
|
13
13
|
import { BaseController } from "@metamask/base-controller";
|
|
14
|
-
import { parseCaipAssetType } from "@metamask/utils";
|
|
14
|
+
import { isCaipChainId, isStrictHexString, parseCaipAssetType, parseCaipChainId } from "@metamask/utils";
|
|
15
15
|
import { Mutex } from "async-mutex";
|
|
16
16
|
import BigNumberJS from "bignumber.js";
|
|
17
17
|
import $lodash from "lodash";
|
|
18
18
|
const { isEqual } = $lodash;
|
|
19
|
+
import { AccountsApiDataSource } from "./data-sources/AccountsApiDataSource.mjs";
|
|
20
|
+
import { BackendWebsocketDataSource } from "./data-sources/BackendWebsocketDataSource.mjs";
|
|
21
|
+
import { PriceDataSource } from "./data-sources/PriceDataSource.mjs";
|
|
22
|
+
import { RpcDataSource } from "./data-sources/RpcDataSource.mjs";
|
|
23
|
+
import { SnapDataSource } from "./data-sources/SnapDataSource.mjs";
|
|
24
|
+
import { StakedBalanceDataSource } from "./data-sources/StakedBalanceDataSource.mjs";
|
|
25
|
+
import { TokenDataSource } from "./data-sources/TokenDataSource.mjs";
|
|
19
26
|
import { projectLogger, createModuleLogger } from "./logger.mjs";
|
|
27
|
+
import { DetectionMiddleware } from "./middlewares/DetectionMiddleware.mjs";
|
|
20
28
|
import { normalizeAssetId } from "./utils.mjs";
|
|
21
29
|
// ============================================================================
|
|
22
30
|
// CONTROLLER CONSTANTS
|
|
23
31
|
// ============================================================================
|
|
24
32
|
const CONTROLLER_NAME = 'AssetsController';
|
|
33
|
+
/** Method names exposed as messenger actions (AssetsController:getAssets, etc.) */
|
|
34
|
+
const MESSENGER_EXPOSED_METHODS = [
|
|
35
|
+
'getAssets',
|
|
36
|
+
'getAssetsBalance',
|
|
37
|
+
'getAssetMetadata',
|
|
38
|
+
'getAssetsPrice',
|
|
39
|
+
'addCustomAsset',
|
|
40
|
+
'removeCustomAsset',
|
|
41
|
+
'getCustomAssets',
|
|
42
|
+
'hideAsset',
|
|
43
|
+
'unhideAsset',
|
|
44
|
+
];
|
|
25
45
|
/** Default polling interval hint for data sources (30 seconds) */
|
|
26
46
|
const DEFAULT_POLLING_INTERVAL_MS = 30000;
|
|
27
47
|
const log = createModuleLogger(projectLogger, CONTROLLER_NAME);
|
|
@@ -32,7 +52,7 @@ const log = createModuleLogger(projectLogger, CONTROLLER_NAME);
|
|
|
32
52
|
*/
|
|
33
53
|
export function getDefaultAssetsControllerState() {
|
|
34
54
|
return {
|
|
35
|
-
|
|
55
|
+
assetsInfo: {},
|
|
36
56
|
assetsBalance: {},
|
|
37
57
|
assetsPrice: {},
|
|
38
58
|
customAssets: {},
|
|
@@ -43,7 +63,7 @@ export function getDefaultAssetsControllerState() {
|
|
|
43
63
|
// STATE METADATA
|
|
44
64
|
// ============================================================================
|
|
45
65
|
const stateMetadata = {
|
|
46
|
-
|
|
66
|
+
assetsInfo: {
|
|
47
67
|
persist: true,
|
|
48
68
|
includeInStateLogs: false,
|
|
49
69
|
includeInDebugSnapshot: false,
|
|
@@ -91,11 +111,11 @@ function extractChainId(assetId) {
|
|
|
91
111
|
*/
|
|
92
112
|
function normalizeResponse(response) {
|
|
93
113
|
const normalized = {};
|
|
94
|
-
if (response.
|
|
95
|
-
normalized.
|
|
96
|
-
for (const [assetId, metadata] of Object.entries(response.
|
|
114
|
+
if (response.assetsInfo) {
|
|
115
|
+
normalized.assetsInfo = {};
|
|
116
|
+
for (const [assetId, metadata] of Object.entries(response.assetsInfo)) {
|
|
97
117
|
const normalizedId = normalizeAssetId(assetId);
|
|
98
|
-
normalized.
|
|
118
|
+
normalized.assetsInfo[normalizedId] = metadata;
|
|
99
119
|
}
|
|
100
120
|
}
|
|
101
121
|
if (response.assetsPrice) {
|
|
@@ -147,13 +167,8 @@ function normalizeResponse(response) {
|
|
|
147
167
|
* based on which chains they support. When active chains change, the controller
|
|
148
168
|
* dynamically adjusts subscriptions.
|
|
149
169
|
*
|
|
150
|
-
* 4. **
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* ## App Lifecycle
|
|
154
|
-
*
|
|
155
|
-
* - **App Opened** (`AppStateController:appOpened`): Starts subscriptions, fetches initial data
|
|
156
|
-
* - **App Closed** (`AppStateController:appClosed`): Stops all subscriptions to conserve resources
|
|
170
|
+
* 4. **Keyring Lifecycle**: Listens to KeyringController unlock/lock events to
|
|
171
|
+
* start/stop subscriptions when the wallet is unlocked or locked.
|
|
157
172
|
*
|
|
158
173
|
* ## Architecture
|
|
159
174
|
*
|
|
@@ -162,7 +177,7 @@ function normalizeResponse(response) {
|
|
|
162
177
|
* - The controller does NOT manage polling - it simply receives pushed updates
|
|
163
178
|
*/
|
|
164
179
|
export class AssetsController extends BaseController {
|
|
165
|
-
constructor({ messenger, state = {}, defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS, isEnabled = () => true, }) {
|
|
180
|
+
constructor({ messenger, state = {}, defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS, isEnabled = () => true, isBasicFunctionality, subscribeToBasicFunctionalityChange, queryApiClient, rpcDataSourceConfig, trackMetaMetricsEvent, accountsApiDataSourceConfig, priceDataSourceConfig, stakedBalanceDataSourceConfig, }) {
|
|
166
181
|
super({
|
|
167
182
|
name: CONTROLLER_NAME,
|
|
168
183
|
messenger,
|
|
@@ -175,8 +190,14 @@ export class AssetsController extends BaseController {
|
|
|
175
190
|
_AssetsController_instances.add(this);
|
|
176
191
|
/** Whether the controller is enabled */
|
|
177
192
|
_AssetsController_isEnabled.set(this, void 0);
|
|
193
|
+
/** Getter for basic functionality (only balance fetch/subscribe use RPC; token/price API not used). No attribute stored. */
|
|
194
|
+
_AssetsController_isBasicFunctionality.set(this, void 0);
|
|
178
195
|
/** Default update interval hint passed to data sources */
|
|
179
196
|
_AssetsController_defaultUpdateInterval.set(this, void 0);
|
|
197
|
+
/** Optional callback for first init/fetch MetaMetrics (duration). */
|
|
198
|
+
_AssetsController_trackMetaMetricsEvent.set(this, void 0);
|
|
199
|
+
/** Whether we have already reported first init fetch for this session (reset on #stop). */
|
|
200
|
+
_AssetsController_firstInitFetchReported.set(this, false);
|
|
180
201
|
_AssetsController_controllerMutex.set(this, new Mutex());
|
|
181
202
|
/**
|
|
182
203
|
* Active balance subscriptions keyed by account ID.
|
|
@@ -187,79 +208,107 @@ export class AssetsController extends BaseController {
|
|
|
187
208
|
_AssetsController_activeSubscriptions.set(this, new Map());
|
|
188
209
|
/** Currently enabled chains from NetworkEnablementController */
|
|
189
210
|
_AssetsController_enabledChains.set(this, new Set());
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
211
|
+
_AssetsController_backendWebsocketDataSource.set(this, void 0);
|
|
212
|
+
_AssetsController_accountsApiDataSource.set(this, void 0);
|
|
213
|
+
_AssetsController_snapDataSource.set(this, void 0);
|
|
214
|
+
_AssetsController_rpcDataSource.set(this, void 0);
|
|
215
|
+
_AssetsController_stakedBalanceDataSource.set(this, void 0);
|
|
216
|
+
_AssetsController_priceDataSource.set(this, void 0);
|
|
217
|
+
_AssetsController_detectionMiddleware.set(this, void 0);
|
|
218
|
+
_AssetsController_tokenDataSource.set(this, void 0);
|
|
219
|
+
_AssetsController_unsubscribeBasicFunctionality.set(this, null);
|
|
196
220
|
__classPrivateFieldSet(this, _AssetsController_isEnabled, isEnabled(), "f");
|
|
221
|
+
__classPrivateFieldSet(this, _AssetsController_isBasicFunctionality, isBasicFunctionality ?? (() => true), "f");
|
|
197
222
|
__classPrivateFieldSet(this, _AssetsController_defaultUpdateInterval, defaultUpdateInterval, "f");
|
|
223
|
+
__classPrivateFieldSet(this, _AssetsController_trackMetaMetricsEvent, trackMetaMetricsEvent, "f");
|
|
224
|
+
const rpcConfig = rpcDataSourceConfig ?? {};
|
|
225
|
+
const onActiveChainsUpdated = (dataSourceName, chains, previousChains) => {
|
|
226
|
+
this.handleActiveChainsUpdate(dataSourceName, chains, previousChains);
|
|
227
|
+
};
|
|
228
|
+
__classPrivateFieldSet(this, _AssetsController_backendWebsocketDataSource, new BackendWebsocketDataSource({
|
|
229
|
+
messenger: this.messenger,
|
|
230
|
+
queryApiClient,
|
|
231
|
+
onActiveChainsUpdated,
|
|
232
|
+
}), "f");
|
|
233
|
+
__classPrivateFieldSet(this, _AssetsController_accountsApiDataSource, new AccountsApiDataSource({
|
|
234
|
+
queryApiClient,
|
|
235
|
+
onActiveChainsUpdated,
|
|
236
|
+
...accountsApiDataSourceConfig,
|
|
237
|
+
}), "f");
|
|
238
|
+
__classPrivateFieldSet(this, _AssetsController_snapDataSource, new SnapDataSource({
|
|
239
|
+
messenger: this.messenger,
|
|
240
|
+
onActiveChainsUpdated,
|
|
241
|
+
}), "f");
|
|
242
|
+
__classPrivateFieldSet(this, _AssetsController_rpcDataSource, new RpcDataSource({
|
|
243
|
+
messenger: this.messenger,
|
|
244
|
+
onActiveChainsUpdated,
|
|
245
|
+
...rpcConfig,
|
|
246
|
+
}), "f");
|
|
247
|
+
__classPrivateFieldSet(this, _AssetsController_stakedBalanceDataSource, new StakedBalanceDataSource({
|
|
248
|
+
messenger: this.messenger,
|
|
249
|
+
onActiveChainsUpdated,
|
|
250
|
+
...stakedBalanceDataSourceConfig,
|
|
251
|
+
}), "f");
|
|
252
|
+
__classPrivateFieldSet(this, _AssetsController_tokenDataSource, new TokenDataSource({
|
|
253
|
+
queryApiClient,
|
|
254
|
+
}), "f");
|
|
255
|
+
__classPrivateFieldSet(this, _AssetsController_priceDataSource, new PriceDataSource({
|
|
256
|
+
queryApiClient,
|
|
257
|
+
...priceDataSourceConfig,
|
|
258
|
+
}), "f");
|
|
259
|
+
__classPrivateFieldSet(this, _AssetsController_detectionMiddleware, new DetectionMiddleware(), "f");
|
|
198
260
|
if (!__classPrivateFieldGet(this, _AssetsController_isEnabled, "f")) {
|
|
199
261
|
log('AssetsController is disabled, skipping initialization');
|
|
200
262
|
return;
|
|
201
263
|
}
|
|
202
264
|
log('Initializing AssetsController', {
|
|
203
|
-
defaultUpdateInterval,
|
|
265
|
+
defaultUpdateInterval: __classPrivateFieldGet(this, _AssetsController_defaultUpdateInterval, "f"),
|
|
204
266
|
});
|
|
205
267
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_initializeState).call(this);
|
|
206
268
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeToEvents).call(this);
|
|
207
269
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_registerActionHandlers).call(this);
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// ============================================================================
|
|
217
|
-
// DATA SOURCE MANAGEMENT
|
|
218
|
-
// ============================================================================
|
|
219
|
-
/**
|
|
220
|
-
* Register data sources with the controller.
|
|
221
|
-
* Order of the array determines subscription order.
|
|
222
|
-
*
|
|
223
|
-
* Data sources report chain changes by calling `AssetsController:activeChainsUpdate` action.
|
|
224
|
-
*
|
|
225
|
-
* @param dataSourceIds - Array of data source identifiers to register.
|
|
226
|
-
*/
|
|
227
|
-
registerDataSources(dataSourceIds) {
|
|
228
|
-
for (const id of dataSourceIds) {
|
|
229
|
-
log('Registering data source', { id });
|
|
230
|
-
// Initialize available chains tracking for this source
|
|
231
|
-
__classPrivateFieldGet(this, _AssetsController_dataSources, "f").set(id, new Set());
|
|
270
|
+
// Subscriptions start only on KeyringController:unlock -> #start(), not here.
|
|
271
|
+
// Subscribe to basic-functionality changes after construction so a synchronous
|
|
272
|
+
// onChange during subscribe cannot run before data sources are initialized.
|
|
273
|
+
if (subscribeToBasicFunctionalityChange) {
|
|
274
|
+
const unsubscribe = subscribeToBasicFunctionalityChange((isBasic) => this.handleBasicFunctionalityChange(isBasic));
|
|
275
|
+
if (typeof unsubscribe === 'function') {
|
|
276
|
+
__classPrivateFieldSet(this, _AssetsController_unsubscribeBasicFunctionality, unsubscribe, "f");
|
|
277
|
+
}
|
|
232
278
|
}
|
|
233
279
|
}
|
|
234
280
|
// ============================================================================
|
|
235
281
|
// DATA SOURCE CHAIN MANAGEMENT
|
|
236
282
|
// ============================================================================
|
|
237
283
|
/**
|
|
238
|
-
* Handle when a data source's
|
|
239
|
-
*
|
|
240
|
-
*
|
|
284
|
+
* Handle when a data source's supported chains change.
|
|
285
|
+
* Used to refresh balance subscriptions and run a one-time fetch when a new chain is supported.
|
|
286
|
+
*
|
|
287
|
+
* - On any add/remove: re-subscribes to data sources so chain assignment stays correct.
|
|
288
|
+
* - When chains are added: fetches balances for the new chains (for selected accounts on enabled networks).
|
|
241
289
|
*
|
|
242
|
-
*
|
|
290
|
+
* Controller does not store chains; sources report via this callback. previousChains is required for diff.
|
|
243
291
|
*
|
|
244
292
|
* @param dataSourceId - The identifier of the data source reporting the change.
|
|
245
|
-
* @param activeChains -
|
|
293
|
+
* @param activeChains - Currently active (supported and available) chain IDs for this source.
|
|
294
|
+
* @param previousChains - Previous chains; used to compute added/removed.
|
|
246
295
|
*/
|
|
247
|
-
handleActiveChainsUpdate(dataSourceId, activeChains) {
|
|
296
|
+
handleActiveChainsUpdate(dataSourceId, activeChains, previousChains) {
|
|
297
|
+
if (!__classPrivateFieldGet(this, _AssetsController_isEnabled, "f")) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
248
300
|
log('Data source active chains changed', {
|
|
249
301
|
dataSourceId,
|
|
250
302
|
chainCount: activeChains.length,
|
|
251
303
|
chains: activeChains,
|
|
252
304
|
});
|
|
253
|
-
const
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
// Check for changes
|
|
258
|
-
const addedChains = activeChains.filter((chain) => !previousChains.has(chain));
|
|
259
|
-
const removedChains = Array.from(previousChains).filter((chain) => !newChains.has(chain));
|
|
305
|
+
const previous = previousChains;
|
|
306
|
+
const previousSet = new Set(previous);
|
|
307
|
+
const addedChains = activeChains.filter((ch) => !previousSet.has(ch));
|
|
308
|
+
const removedChains = previous.filter((ch) => !activeChains.includes(ch));
|
|
260
309
|
if (addedChains.length > 0 || removedChains.length > 0) {
|
|
261
310
|
// Refresh subscriptions to use updated data source availability
|
|
262
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
311
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
263
312
|
}
|
|
264
313
|
// If chains were added and we have selected accounts, do one-time fetch
|
|
265
314
|
if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
|
|
@@ -289,22 +338,39 @@ export class AssetsController extends BaseController {
|
|
|
289
338
|
customAssets.push(...accountCustomAssets);
|
|
290
339
|
}
|
|
291
340
|
if (options?.forceUpdate) {
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
this.messenger.call('SnapDataSource:getAssetsMiddleware'),
|
|
295
|
-
this.messenger.call('RpcDataSource:getAssetsMiddleware'),
|
|
296
|
-
this.messenger.call('DetectionMiddleware:getAssetsMiddleware'),
|
|
297
|
-
this.messenger.call('TokenDataSource:getAssetsMiddleware'),
|
|
298
|
-
this.messenger.call('PriceDataSource:getAssetsMiddleware'),
|
|
299
|
-
], {
|
|
300
|
-
accounts,
|
|
301
|
-
chainIds,
|
|
341
|
+
const startTime = Date.now();
|
|
342
|
+
const request = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
|
|
302
343
|
assetTypes,
|
|
303
344
|
dataTypes,
|
|
304
345
|
customAssets: customAssets.length > 0 ? customAssets : undefined,
|
|
305
346
|
forceUpdate: true,
|
|
306
347
|
});
|
|
348
|
+
const sources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
349
|
+
? [
|
|
350
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
|
|
351
|
+
__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"),
|
|
352
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f"),
|
|
353
|
+
__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"),
|
|
354
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
|
|
355
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
|
|
356
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
|
|
357
|
+
]
|
|
358
|
+
: [
|
|
359
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f"),
|
|
360
|
+
__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"),
|
|
361
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
|
|
362
|
+
];
|
|
363
|
+
const { response, durationByDataSource } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, sources, request);
|
|
307
364
|
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, response);
|
|
365
|
+
if (__classPrivateFieldGet(this, _AssetsController_trackMetaMetricsEvent, "f") && !__classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")) {
|
|
366
|
+
__classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, true, "f");
|
|
367
|
+
const durationMs = Date.now() - startTime;
|
|
368
|
+
__classPrivateFieldGet(this, _AssetsController_trackMetaMetricsEvent, "f").call(this, {
|
|
369
|
+
durationMs,
|
|
370
|
+
chainIds,
|
|
371
|
+
durationByDataSource,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
308
374
|
}
|
|
309
375
|
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetsFromState).call(this, accounts, chainIds, assetTypes);
|
|
310
376
|
}
|
|
@@ -329,7 +395,7 @@ export class AssetsController extends BaseController {
|
|
|
329
395
|
return result;
|
|
330
396
|
}
|
|
331
397
|
getAssetMetadata(assetId) {
|
|
332
|
-
return this.state.
|
|
398
|
+
return this.state.assetsInfo[assetId];
|
|
333
399
|
}
|
|
334
400
|
async getAssetsPrice(accounts, options) {
|
|
335
401
|
const assets = await this.getAssets(accounts, {
|
|
@@ -457,33 +523,33 @@ export class AssetsController extends BaseController {
|
|
|
457
523
|
}
|
|
458
524
|
});
|
|
459
525
|
}
|
|
526
|
+
// ============================================================================
|
|
527
|
+
// SUBSCRIPTIONS
|
|
528
|
+
// ============================================================================
|
|
460
529
|
/**
|
|
461
530
|
* Subscribe to price updates for all assets held by the given accounts.
|
|
462
531
|
* Polls PriceDataSource which fetches prices from balance state.
|
|
463
532
|
*
|
|
464
533
|
* @param accounts - Accounts to subscribe price updates for.
|
|
465
534
|
* @param chainIds - Chain IDs to filter prices for.
|
|
466
|
-
* @param options - Subscription options.
|
|
467
|
-
* @param options.updateInterval - Polling interval in ms.
|
|
468
535
|
*/
|
|
469
|
-
subscribeAssetsPrice(accounts, chainIds
|
|
470
|
-
|
|
536
|
+
subscribeAssetsPrice(accounts, chainIds) {
|
|
537
|
+
if (!__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
471
540
|
const subscriptionKey = 'ds:PriceDataSource';
|
|
472
541
|
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
473
542
|
const isUpdate = existingSubscription !== undefined;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
.call('PriceDataSource:subscribe', {
|
|
477
|
-
request: {
|
|
478
|
-
accounts,
|
|
479
|
-
chainIds,
|
|
543
|
+
const subscribeReq = {
|
|
544
|
+
request: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
|
|
480
545
|
dataTypes: ['price'],
|
|
481
|
-
|
|
482
|
-
},
|
|
546
|
+
}),
|
|
483
547
|
subscriptionId: subscriptionKey,
|
|
484
548
|
isUpdate,
|
|
485
|
-
|
|
486
|
-
|
|
549
|
+
onAssetsUpdate: (response) => this.handleAssetsUpdate(response, 'PriceDataSource'),
|
|
550
|
+
getAssetsState: () => this.state,
|
|
551
|
+
};
|
|
552
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").subscribe(subscribeReq).catch(console.error);
|
|
487
553
|
// Track subscription
|
|
488
554
|
const subscription = {
|
|
489
555
|
chains: chainIds,
|
|
@@ -505,46 +571,70 @@ export class AssetsController extends BaseController {
|
|
|
505
571
|
if (!existingSubscription) {
|
|
506
572
|
return;
|
|
507
573
|
}
|
|
508
|
-
|
|
509
|
-
this.messenger
|
|
510
|
-
.call('PriceDataSource:unsubscribe', subscriptionKey)
|
|
511
|
-
.catch(console.error);
|
|
574
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").unsubscribe(subscriptionKey).catch(console.error);
|
|
512
575
|
existingSubscription.unsubscribe();
|
|
513
576
|
}
|
|
577
|
+
/**
|
|
578
|
+
* Handle basic functionality toggle change. Call this from the consumer (extension or mobile)
|
|
579
|
+
* when the user changes the "Basic functionality" setting. Refreshes subscriptions so the
|
|
580
|
+
* current {@link AssetsControllerOptions.isBasicFunctionality} getter is used (true = APIs on,
|
|
581
|
+
* false = RPC only).
|
|
582
|
+
*
|
|
583
|
+
* @param _isBasic - The new value (for call-site clarity; the getter is the source of truth).
|
|
584
|
+
*/
|
|
585
|
+
handleBasicFunctionalityChange(_isBasic) {
|
|
586
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this);
|
|
587
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
588
|
+
}
|
|
514
589
|
/**
|
|
515
590
|
* Handle assets updated from a data source.
|
|
516
|
-
* Called via
|
|
591
|
+
* Called via the onAssetsUpdate callback passed in SubscriptionRequest when the controller subscribes to a data source.
|
|
592
|
+
* Enriches the response with token metadata (via middlewares) before updating state.
|
|
517
593
|
*
|
|
518
594
|
* @param response - The data response with updated assets
|
|
519
595
|
* @param sourceId - The data source ID reporting the update
|
|
596
|
+
* @param request - Optional original request for context when enriching
|
|
520
597
|
*/
|
|
521
|
-
async handleAssetsUpdate(response, sourceId) {
|
|
598
|
+
async handleAssetsUpdate(response, sourceId, request) {
|
|
522
599
|
log('Assets updated from data source', {
|
|
523
600
|
sourceId,
|
|
524
601
|
hasBalance: Boolean(response.assetsBalance),
|
|
525
602
|
hasPrice: Boolean(response.assetsPrice),
|
|
526
603
|
});
|
|
527
|
-
|
|
604
|
+
// Run through enrichment middlewares (Event Stack: Detection → Token → Price)
|
|
605
|
+
// Include 'metadata' in dataTypes so TokenDataSource runs to enrich detected assets
|
|
606
|
+
const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, [__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"), __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f")], request ?? {
|
|
607
|
+
accountsWithSupportedChains: [],
|
|
608
|
+
chainIds: [],
|
|
609
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
610
|
+
}, response);
|
|
611
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, enrichedResponse);
|
|
528
612
|
}
|
|
529
613
|
// ============================================================================
|
|
530
614
|
// CLEANUP
|
|
531
615
|
// ============================================================================
|
|
532
616
|
destroy() {
|
|
533
617
|
log('Destroying AssetsController', {
|
|
534
|
-
dataSourceCount: __classPrivateFieldGet(this,
|
|
618
|
+
dataSourceCount: __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get).length,
|
|
535
619
|
subscriptionCount: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size,
|
|
536
620
|
});
|
|
537
|
-
//
|
|
538
|
-
__classPrivateFieldGet(this,
|
|
621
|
+
// Destroy instantiated data sources
|
|
622
|
+
__classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f")?.destroy?.();
|
|
623
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f")?.destroy?.();
|
|
624
|
+
__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f")?.destroy?.();
|
|
625
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")?.destroy?.();
|
|
626
|
+
__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f")?.destroy?.();
|
|
539
627
|
// Stop all active subscriptions
|
|
540
628
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this);
|
|
629
|
+
if (__classPrivateFieldGet(this, _AssetsController_unsubscribeBasicFunctionality, "f")) {
|
|
630
|
+
__classPrivateFieldGet(this, _AssetsController_unsubscribeBasicFunctionality, "f").call(this);
|
|
631
|
+
__classPrivateFieldSet(this, _AssetsController_unsubscribeBasicFunctionality, null, "f");
|
|
632
|
+
}
|
|
541
633
|
// Unregister action handlers
|
|
542
634
|
this.messenger.unregisterActionHandler('AssetsController:getAssets');
|
|
543
635
|
this.messenger.unregisterActionHandler('AssetsController:getAssetsBalance');
|
|
544
636
|
this.messenger.unregisterActionHandler('AssetsController:getAssetMetadata');
|
|
545
637
|
this.messenger.unregisterActionHandler('AssetsController:getAssetsPrice');
|
|
546
|
-
this.messenger.unregisterActionHandler('AssetsController:activeChainsUpdate');
|
|
547
|
-
this.messenger.unregisterActionHandler('AssetsController:assetsUpdate');
|
|
548
638
|
this.messenger.unregisterActionHandler('AssetsController:addCustomAsset');
|
|
549
639
|
this.messenger.unregisterActionHandler('AssetsController:removeCustomAsset');
|
|
550
640
|
this.messenger.unregisterActionHandler('AssetsController:getCustomAssets');
|
|
@@ -552,8 +642,15 @@ export class AssetsController extends BaseController {
|
|
|
552
642
|
this.messenger.unregisterActionHandler('AssetsController:unhideAsset');
|
|
553
643
|
}
|
|
554
644
|
}
|
|
555
|
-
_AssetsController_isEnabled = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(),
|
|
645
|
+
_AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trackMetaMetricsEvent = new WeakMap(), _AssetsController_firstInitFetchReported = 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_stakedBalanceDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_selectedAccounts_get = function _AssetsController_selectedAccounts_get() {
|
|
556
646
|
return this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup');
|
|
647
|
+
}, _AssetsController_allBalanceDataSources_get = function _AssetsController_allBalanceDataSources_get() {
|
|
648
|
+
return [
|
|
649
|
+
__classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f"),
|
|
650
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
|
|
651
|
+
__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"),
|
|
652
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f"),
|
|
653
|
+
];
|
|
557
654
|
}, _AssetsController_initializeState = function _AssetsController_initializeState() {
|
|
558
655
|
const { enabledNetworkMap } = this.messenger.call('NetworkEnablementController:getState');
|
|
559
656
|
__classPrivateFieldSet(this, _AssetsController_enabledChains, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_extractEnabledChains).call(this, enabledNetworkMap), "f");
|
|
@@ -581,7 +678,7 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_defaultUpdateInte
|
|
|
581
678
|
}
|
|
582
679
|
return chains;
|
|
583
680
|
}, _AssetsController_normalizeChainReference = function _AssetsController_normalizeChainReference(namespace, reference) {
|
|
584
|
-
if (namespace === 'eip155' && reference
|
|
681
|
+
if (namespace === 'eip155' && isStrictHexString(reference)) {
|
|
585
682
|
// Convert hex to decimal for EIP155 chains
|
|
586
683
|
return parseInt(reference, 16).toString();
|
|
587
684
|
}
|
|
@@ -595,38 +692,38 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_defaultUpdateInte
|
|
|
595
692
|
this.messenger.subscribe('NetworkEnablementController:stateChange', ({ enabledNetworkMap }) => {
|
|
596
693
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleEnabledNetworksChanged).call(this, enabledNetworkMap).catch(console.error);
|
|
597
694
|
});
|
|
598
|
-
// App lifecycle: start when opened, stop when closed
|
|
599
|
-
this.messenger.subscribe('AppStateController:appOpened', () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_start).call(this));
|
|
600
|
-
this.messenger.subscribe('AppStateController:appClosed', () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this));
|
|
601
695
|
// Keyring lifecycle: start when unlocked, stop when locked
|
|
602
696
|
this.messenger.subscribe('KeyringController:unlock', () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_start).call(this));
|
|
603
697
|
this.messenger.subscribe('KeyringController:lock', () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this));
|
|
604
698
|
}, _AssetsController_registerActionHandlers = function _AssetsController_registerActionHandlers() {
|
|
605
|
-
this.messenger.
|
|
606
|
-
this.messenger.registerActionHandler('AssetsController:getAssetsBalance', this.getAssetsBalance.bind(this));
|
|
607
|
-
this.messenger.registerActionHandler('AssetsController:getAssetMetadata', this.getAssetMetadata.bind(this));
|
|
608
|
-
this.messenger.registerActionHandler('AssetsController:getAssetsPrice', this.getAssetsPrice.bind(this));
|
|
609
|
-
this.messenger.registerActionHandler('AssetsController:activeChainsUpdate', this.handleActiveChainsUpdate.bind(this));
|
|
610
|
-
this.messenger.registerActionHandler('AssetsController:assetsUpdate', this.handleAssetsUpdate.bind(this));
|
|
611
|
-
this.messenger.registerActionHandler('AssetsController:addCustomAsset', this.addCustomAsset.bind(this));
|
|
612
|
-
this.messenger.registerActionHandler('AssetsController:removeCustomAsset', this.removeCustomAsset.bind(this));
|
|
613
|
-
this.messenger.registerActionHandler('AssetsController:getCustomAssets', this.getCustomAssets.bind(this));
|
|
614
|
-
this.messenger.registerActionHandler('AssetsController:hideAsset', this.hideAsset.bind(this));
|
|
615
|
-
this.messenger.registerActionHandler('AssetsController:unhideAsset', this.unhideAsset.bind(this));
|
|
699
|
+
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
616
700
|
}, _AssetsController_executeMiddlewares =
|
|
617
701
|
// ============================================================================
|
|
618
702
|
// MIDDLEWARE EXECUTION
|
|
619
703
|
// ============================================================================
|
|
620
704
|
/**
|
|
621
705
|
* Execute middlewares with request/response context.
|
|
706
|
+
* Returns response and exclusive duration per source (sum ≈ wall time).
|
|
622
707
|
*
|
|
623
|
-
* @param
|
|
708
|
+
* @param sources - Data sources or middlewares with getName() and assetsMiddleware (executed in order).
|
|
624
709
|
* @param request - The data request.
|
|
625
710
|
* @param initialResponse - Optional initial response (for enriching existing data).
|
|
626
|
-
* @returns
|
|
711
|
+
* @returns Response and durationByDataSource (exclusive ms per source name).
|
|
627
712
|
*/
|
|
628
|
-
async function _AssetsController_executeMiddlewares(
|
|
629
|
-
const
|
|
713
|
+
async function _AssetsController_executeMiddlewares(sources, request, initialResponse = {}) {
|
|
714
|
+
const names = sources.map((source) => source.getName());
|
|
715
|
+
const middlewares = sources.map((source) => source.assetsMiddleware);
|
|
716
|
+
const inclusive = [];
|
|
717
|
+
const wrapped = middlewares.map((middleware, i) => (async (ctx, next) => {
|
|
718
|
+
const start = Date.now();
|
|
719
|
+
try {
|
|
720
|
+
return await middleware(ctx, next);
|
|
721
|
+
}
|
|
722
|
+
finally {
|
|
723
|
+
inclusive[i] = Date.now() - start;
|
|
724
|
+
}
|
|
725
|
+
}));
|
|
726
|
+
const chain = wrapped.reduceRight((next, middleware) => async (ctx) => {
|
|
630
727
|
try {
|
|
631
728
|
return await middleware(ctx, next);
|
|
632
729
|
}
|
|
@@ -640,33 +737,16 @@ async function _AssetsController_executeMiddlewares(middlewares, request, initia
|
|
|
640
737
|
response: initialResponse,
|
|
641
738
|
getAssetsState: () => this.state,
|
|
642
739
|
});
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
if (!availableChains || availableChains.size === 0) {
|
|
651
|
-
continue;
|
|
652
|
-
}
|
|
653
|
-
const chainsForThisSource = [];
|
|
654
|
-
for (const chainId of remainingChains) {
|
|
655
|
-
// Check if this chain is available on this source
|
|
656
|
-
if (availableChains.has(chainId)) {
|
|
657
|
-
chainsForThisSource.push(chainId);
|
|
658
|
-
remainingChains.delete(chainId);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
if (chainsForThisSource.length > 0) {
|
|
662
|
-
assignment.set(sourceId, chainsForThisSource);
|
|
663
|
-
log('Assigned chains to data source', {
|
|
664
|
-
sourceId,
|
|
665
|
-
chains: chainsForThisSource,
|
|
666
|
-
});
|
|
740
|
+
const durationByDataSource = {};
|
|
741
|
+
for (let i = 0; i < inclusive.length; i++) {
|
|
742
|
+
const nextInc = i + 1 < inclusive.length ? (inclusive[i + 1] ?? 0) : 0;
|
|
743
|
+
const exclusive = Math.max(0, (inclusive[i] ?? 0) - nextInc);
|
|
744
|
+
const name = names[i];
|
|
745
|
+
if (name !== undefined) {
|
|
746
|
+
durationByDataSource[name] = exclusive;
|
|
667
747
|
}
|
|
668
748
|
}
|
|
669
|
-
return
|
|
749
|
+
return { response: result.response, durationByDataSource };
|
|
670
750
|
}, _AssetsController_updateState =
|
|
671
751
|
// ============================================================================
|
|
672
752
|
// STATE MANAGEMENT
|
|
@@ -685,12 +765,12 @@ async function _AssetsController_updateState(response) {
|
|
|
685
765
|
const changedMetadata = [];
|
|
686
766
|
this.update((state) => {
|
|
687
767
|
// Use type assertions to avoid deep type instantiation issues with Immer Draft types
|
|
688
|
-
const metadata = state.
|
|
768
|
+
const metadata = state.assetsInfo;
|
|
689
769
|
const balances = state.assetsBalance;
|
|
690
770
|
const prices = state.assetsPrice;
|
|
691
|
-
if (normalizedResponse.
|
|
692
|
-
for (const [key, value] of Object.entries(normalizedResponse.
|
|
693
|
-
if (!isEqual(previousState.
|
|
771
|
+
if (normalizedResponse.assetsInfo) {
|
|
772
|
+
for (const [key, value] of Object.entries(normalizedResponse.assetsInfo)) {
|
|
773
|
+
if (!isEqual(previousState.assetsInfo[key], value)) {
|
|
694
774
|
changedMetadata.push(key);
|
|
695
775
|
}
|
|
696
776
|
metadata[key] = value;
|
|
@@ -795,7 +875,7 @@ async function _AssetsController_updateState(response) {
|
|
|
795
875
|
const accountBalances = this.state.assetsBalance[account.id] ?? {};
|
|
796
876
|
for (const [assetId, balance] of Object.entries(accountBalances)) {
|
|
797
877
|
const typedAssetId = assetId;
|
|
798
|
-
const metadataRaw = this.state.
|
|
878
|
+
const metadataRaw = this.state.assetsInfo[typedAssetId];
|
|
799
879
|
// Skip assets without metadata
|
|
800
880
|
if (!metadataRaw) {
|
|
801
881
|
continue;
|
|
@@ -860,98 +940,112 @@ async function _AssetsController_updateState(response) {
|
|
|
860
940
|
selectedAccountCount: __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length,
|
|
861
941
|
enabledChainCount: __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").size,
|
|
862
942
|
});
|
|
863
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
});
|
|
871
|
-
}
|
|
943
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
944
|
+
this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {
|
|
945
|
+
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
946
|
+
forceUpdate: true,
|
|
947
|
+
}).catch((error) => {
|
|
948
|
+
log('Failed to fetch assets', error);
|
|
949
|
+
});
|
|
872
950
|
}, _AssetsController_stop = function _AssetsController_stop() {
|
|
873
951
|
log('Stopping asset tracking', {
|
|
874
952
|
activeSubscriptionCount: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size,
|
|
875
953
|
hasPriceSubscription: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").has('ds:PriceDataSource'),
|
|
876
954
|
});
|
|
955
|
+
__classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, false, "f");
|
|
877
956
|
// Stop price subscription first (uses direct messenger call)
|
|
878
957
|
this.unsubscribeAssetsPrice();
|
|
879
958
|
// Stop balance subscriptions by properly notifying data sources via messenger
|
|
880
|
-
// This ensures data sources stop their polling timers
|
|
881
|
-
//
|
|
959
|
+
// This ensures data sources stop their polling timers.
|
|
960
|
+
// Use #allBalanceDataSources + staked balance source so we unsubscribe from
|
|
961
|
+
// every source that may have been subscribed.
|
|
962
|
+
const allSources = [
|
|
963
|
+
...__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get),
|
|
964
|
+
__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"),
|
|
965
|
+
];
|
|
882
966
|
const subscriptionKeys = [...__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").keys()];
|
|
883
967
|
for (const subscriptionKey of subscriptionKeys) {
|
|
884
|
-
// Extract sourceId from subscription key (format: "ds:${sourceId}")
|
|
885
968
|
if (subscriptionKey.startsWith('ds:')) {
|
|
886
969
|
const sourceId = subscriptionKey.slice(3);
|
|
887
|
-
|
|
970
|
+
const source = allSources.find((ds) => ds.getName() === sourceId);
|
|
971
|
+
if (source) {
|
|
972
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
|
|
973
|
+
}
|
|
888
974
|
}
|
|
889
975
|
}
|
|
890
976
|
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").clear();
|
|
891
|
-
},
|
|
977
|
+
}, _AssetsController_subscribeAssets = function _AssetsController_subscribeAssets() {
|
|
892
978
|
if (__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length === 0) {
|
|
893
979
|
return;
|
|
894
980
|
}
|
|
895
981
|
// Subscribe to balance updates (batched by data source)
|
|
896
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this)
|
|
982
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [
|
|
983
|
+
...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f"),
|
|
984
|
+
]);
|
|
985
|
+
// Subscribe to staked balance updates (separate from regular balance chain-claiming)
|
|
986
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeStakedBalance).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [
|
|
987
|
+
...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f"),
|
|
988
|
+
]);
|
|
897
989
|
// Subscribe to price updates for all assets held by selected accounts
|
|
898
990
|
this.subscribeAssetsPrice(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
|
|
899
|
-
}, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance() {
|
|
900
|
-
|
|
901
|
-
const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), __classPrivateFieldGet(this, _AssetsController_enabledChains, "f"));
|
|
902
|
-
// Step 2: Split by data source active chains (ordered by priority)
|
|
903
|
-
// Get all chains that need to be subscribed
|
|
991
|
+
}, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance(accounts, chainIds) {
|
|
992
|
+
const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, accounts, new Set(chainIds));
|
|
904
993
|
const remainingChains = new Set(chainToAccounts.keys());
|
|
905
|
-
//
|
|
906
|
-
const
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
continue;
|
|
994
|
+
// When basic functionality is on (getter true), use all balance data sources; when off (getter false), RPC only.
|
|
995
|
+
const balanceDataSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
996
|
+
? __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get)
|
|
997
|
+
: [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
|
|
998
|
+
for (const source of balanceDataSources) {
|
|
999
|
+
const availableChains = new Set(source.getActiveChainsSync());
|
|
1000
|
+
const assignedChains = [];
|
|
1001
|
+
for (const chainId of remainingChains) {
|
|
1002
|
+
if (availableChains.has(chainId)) {
|
|
1003
|
+
assignedChains.push(chainId);
|
|
1004
|
+
remainingChains.delete(chainId);
|
|
1005
|
+
}
|
|
918
1006
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
if (accountsForSource.length === 0) {
|
|
1007
|
+
if (assignedChains.length === 0) {
|
|
1008
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
|
|
922
1009
|
continue;
|
|
923
1010
|
}
|
|
924
|
-
|
|
925
|
-
|
|
1011
|
+
const seenIds = new Set();
|
|
1012
|
+
const accountsForSource = assignedChains
|
|
1013
|
+
.flatMap((chainId) => chainToAccounts.get(chainId) ?? [])
|
|
1014
|
+
.filter((account) => !seenIds.has(account.id) && (seenIds.add(account.id), true));
|
|
1015
|
+
if (accountsForSource.length > 0) {
|
|
1016
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accountsForSource, assignedChains);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}, _AssetsController_subscribeStakedBalance = function _AssetsController_subscribeStakedBalance(accounts, chainIds) {
|
|
1020
|
+
const source = __classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f");
|
|
1021
|
+
if (!source) {
|
|
1022
|
+
return;
|
|
926
1023
|
}
|
|
1024
|
+
const availableChains = new Set(source.getActiveChainsSync());
|
|
1025
|
+
const assignedChains = chainIds.filter((chainId) => availableChains.has(chainId));
|
|
1026
|
+
if (assignedChains.length === 0) {
|
|
1027
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accounts, assignedChains);
|
|
927
1031
|
}, _AssetsController_buildChainToAccountsMap = function _AssetsController_buildChainToAccountsMap(accounts, chainsToSubscribe) {
|
|
928
1032
|
const chainToAccounts = new Map();
|
|
929
1033
|
for (const account of accounts) {
|
|
930
|
-
const
|
|
931
|
-
for (const chainId of accountChains) {
|
|
1034
|
+
for (const chainId of __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account)) {
|
|
932
1035
|
if (!chainsToSubscribe.has(chainId)) {
|
|
933
1036
|
continue;
|
|
934
1037
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
}
|
|
940
|
-
return chainToAccounts;
|
|
941
|
-
}, _AssetsController_getAccountsForChains = function _AssetsController_getAccountsForChains(chains, chainToAccounts) {
|
|
942
|
-
const accountIds = new Set();
|
|
943
|
-
const accounts = [];
|
|
944
|
-
for (const chainId of chains) {
|
|
945
|
-
const chainAccounts = chainToAccounts.get(chainId) ?? [];
|
|
946
|
-
for (const account of chainAccounts) {
|
|
947
|
-
if (!accountIds.has(account.id)) {
|
|
948
|
-
accountIds.add(account.id);
|
|
949
|
-
accounts.push(account);
|
|
1038
|
+
let list = chainToAccounts.get(chainId);
|
|
1039
|
+
if (!list) {
|
|
1040
|
+
list = [];
|
|
1041
|
+
chainToAccounts.set(chainId, list);
|
|
950
1042
|
}
|
|
1043
|
+
list.push(account);
|
|
951
1044
|
}
|
|
952
1045
|
}
|
|
953
|
-
return
|
|
954
|
-
},
|
|
1046
|
+
return chainToAccounts;
|
|
1047
|
+
}, _AssetsController_subscribeDataSource = function _AssetsController_subscribeDataSource(source, accounts, chains) {
|
|
1048
|
+
const sourceId = source.getName();
|
|
955
1049
|
const subscriptionKey = `ds:${sourceId}`;
|
|
956
1050
|
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
957
1051
|
const isUpdate = existingSubscription !== undefined;
|
|
@@ -962,68 +1056,72 @@ async function _AssetsController_updateState(response) {
|
|
|
962
1056
|
accountCount: accounts.length,
|
|
963
1057
|
chainCount: chains.length,
|
|
964
1058
|
});
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
}
|
|
980
|
-
catch (error) {
|
|
981
|
-
console.error(`[AssetsController] Failed to subscribe to '${sourceId}':`, error);
|
|
982
|
-
}
|
|
983
|
-
})().catch(console.error);
|
|
1059
|
+
const subscribeReq = {
|
|
1060
|
+
request: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chains, {
|
|
1061
|
+
assetTypes: ['fungible'],
|
|
1062
|
+
dataTypes: ['balance'],
|
|
1063
|
+
updateInterval: __classPrivateFieldGet(this, _AssetsController_defaultUpdateInterval, "f"),
|
|
1064
|
+
}),
|
|
1065
|
+
subscriptionId: subscriptionKey,
|
|
1066
|
+
isUpdate,
|
|
1067
|
+
onAssetsUpdate: (response) => this.handleAssetsUpdate(response, sourceId),
|
|
1068
|
+
getAssetsState: () => this.state,
|
|
1069
|
+
};
|
|
1070
|
+
source.subscribe(subscribeReq).catch((error) => {
|
|
1071
|
+
console.error(`[AssetsController] Failed to subscribe to '${sourceId}':`, error);
|
|
1072
|
+
});
|
|
984
1073
|
// Track subscription
|
|
985
1074
|
const subscription = {
|
|
986
1075
|
chains,
|
|
987
1076
|
accountId: subscriptionKey,
|
|
988
1077
|
assetTypes: ['fungible'],
|
|
989
|
-
dataTypes: ['balance'
|
|
1078
|
+
dataTypes: ['balance'],
|
|
990
1079
|
unsubscribe: () => {
|
|
991
1080
|
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").delete(subscriptionKey);
|
|
992
1081
|
},
|
|
993
1082
|
};
|
|
994
1083
|
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").set(subscriptionKey, subscription);
|
|
995
|
-
}, _AssetsController_unsubscribeDataSource = function _AssetsController_unsubscribeDataSource(
|
|
996
|
-
const subscriptionKey = `ds:${
|
|
1084
|
+
}, _AssetsController_unsubscribeDataSource = function _AssetsController_unsubscribeDataSource(source) {
|
|
1085
|
+
const subscriptionKey = `ds:${source.getName()}`;
|
|
997
1086
|
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
998
1087
|
if (existingSubscription) {
|
|
999
|
-
|
|
1000
|
-
(async () => {
|
|
1001
|
-
try {
|
|
1002
|
-
await this.messenger.call(`${sourceId}:unsubscribe`, subscriptionKey);
|
|
1003
|
-
}
|
|
1004
|
-
catch {
|
|
1005
|
-
// Ignore errors - source may not have been subscribed
|
|
1006
|
-
}
|
|
1007
|
-
})().catch(() => {
|
|
1008
|
-
// Ignore errors - source may not have been subscribed
|
|
1009
|
-
});
|
|
1088
|
+
source.unsubscribe(subscriptionKey).catch(() => undefined);
|
|
1010
1089
|
existingSubscription.unsubscribe();
|
|
1011
1090
|
}
|
|
1091
|
+
}, _AssetsController_buildDataRequest = function _AssetsController_buildDataRequest(accounts, chainIds, partial = {}) {
|
|
1092
|
+
const chainIdSet = new Set(chainIds);
|
|
1093
|
+
const accountsWithSupportedChains = accounts.map((account) => ({
|
|
1094
|
+
account,
|
|
1095
|
+
supportedChains: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account).filter((chain) => chainIdSet.has(chain)),
|
|
1096
|
+
}));
|
|
1097
|
+
return {
|
|
1098
|
+
accountsWithSupportedChains,
|
|
1099
|
+
chainIds,
|
|
1100
|
+
...partial,
|
|
1101
|
+
};
|
|
1012
1102
|
}, _AssetsController_getEnabledChainsForAccount = function _AssetsController_getEnabledChainsForAccount(account) {
|
|
1013
1103
|
// Account scopes are CAIP-2 chain IDs like "eip155:1", "solana:mainnet", "bip122:..."
|
|
1014
1104
|
const scopes = account.scopes ?? [];
|
|
1015
1105
|
const result = [];
|
|
1016
1106
|
for (const scope of scopes) {
|
|
1017
|
-
const
|
|
1107
|
+
const scopeStr = scope;
|
|
1108
|
+
if (!isCaipChainId(scopeStr)) {
|
|
1109
|
+
result.push(scope);
|
|
1110
|
+
continue;
|
|
1111
|
+
}
|
|
1112
|
+
const { namespace, reference } = parseCaipChainId(scopeStr);
|
|
1018
1113
|
// Wildcard scope (e.g., "eip155:0" means all enabled chains in that namespace)
|
|
1019
1114
|
if (reference === '0') {
|
|
1020
1115
|
for (const chain of __classPrivateFieldGet(this, _AssetsController_enabledChains, "f")) {
|
|
1021
|
-
if (chain
|
|
1022
|
-
|
|
1116
|
+
if (isCaipChainId(chain)) {
|
|
1117
|
+
const chainParsed = parseCaipChainId(chain);
|
|
1118
|
+
if (chainParsed.namespace === namespace) {
|
|
1119
|
+
result.push(chain);
|
|
1120
|
+
}
|
|
1023
1121
|
}
|
|
1024
1122
|
}
|
|
1025
1123
|
}
|
|
1026
|
-
else if (namespace === 'eip155' && reference
|
|
1124
|
+
else if (namespace === 'eip155' && isStrictHexString(reference)) {
|
|
1027
1125
|
// Normalize hex to decimal for EIP155
|
|
1028
1126
|
result.push(`eip155:${parseInt(reference, 16)}`);
|
|
1029
1127
|
}
|
|
@@ -1043,7 +1141,7 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
1043
1141
|
accountIds: accounts.map((a) => a.id),
|
|
1044
1142
|
});
|
|
1045
1143
|
// Subscribe and fetch for the new account group
|
|
1046
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
1144
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1047
1145
|
if (accounts.length > 0) {
|
|
1048
1146
|
await this.getAssets(accounts, {
|
|
1049
1147
|
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
@@ -1077,7 +1175,7 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
1077
1175
|
// Users may want to see historical balances even if the network is currently disabled.
|
|
1078
1176
|
// The data will simply not be updated until the network is re-enabled.
|
|
1079
1177
|
// Refresh subscriptions for new chain set
|
|
1080
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
1178
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1081
1179
|
// Do one-time fetch for newly enabled chains
|
|
1082
1180
|
if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
|
|
1083
1181
|
await this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {
|
|
@@ -1085,28 +1183,5 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
1085
1183
|
forceUpdate: true,
|
|
1086
1184
|
});
|
|
1087
1185
|
}
|
|
1088
|
-
}, _AssetsController_handleSubscriptionUpdate =
|
|
1089
|
-
/**
|
|
1090
|
-
* Handle an async update from a data source subscription.
|
|
1091
|
-
* Enriches response with token metadata before updating state.
|
|
1092
|
-
*
|
|
1093
|
-
* @param response - The data response from the data source.
|
|
1094
|
-
* @param _sourceId - The source ID (unused but kept for logging context).
|
|
1095
|
-
* @param request - Optional original request for context.
|
|
1096
|
-
*/
|
|
1097
|
-
async function _AssetsController_handleSubscriptionUpdate(response, _sourceId, request) {
|
|
1098
|
-
// Run through enrichment middlewares (Event Stack: Detection → Token → Price)
|
|
1099
|
-
// Include 'metadata' in dataTypes so TokenDataSource runs to enrich detected assets
|
|
1100
|
-
const enrichedResponse = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, [
|
|
1101
|
-
this.messenger.call('DetectionMiddleware:getAssetsMiddleware'),
|
|
1102
|
-
this.messenger.call('TokenDataSource:getAssetsMiddleware'),
|
|
1103
|
-
this.messenger.call('PriceDataSource:getAssetsMiddleware'),
|
|
1104
|
-
], request ?? {
|
|
1105
|
-
accounts: [],
|
|
1106
|
-
chainIds: [],
|
|
1107
|
-
dataTypes: ['balance', 'metadata', 'price'],
|
|
1108
|
-
}, response);
|
|
1109
|
-
// Update state
|
|
1110
|
-
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, enrichedResponse);
|
|
1111
1186
|
};
|
|
1112
1187
|
//# sourceMappingURL=AssetsController.mjs.map
|