@metamask-previews/assets-controller 1.0.0-preview-cbcea9611 → 1.0.0-preview-bc3c2ef97

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 CHANGED
@@ -9,7 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Changed
11
11
 
12
- - Hide native tokens on Tempo networks (testnet and mainnet) in `getAssets` method ([#7882](https://github.com/MetaMask/core/pull/7882))
13
12
  - Bump `@metamask/keyring-api` from `^21.0.0` to `^21.5.0` ([#7857](https://github.com/MetaMask/core/pull/7857))
14
13
  - Bump `@metamask/keyring-internal-api` from `^9.0.0` to `^10.0.0` ([#7857](https://github.com/MetaMask/core/pull/7857))
15
14
  - Bump `@metamask/keyring-snap-client` from `^8.0.0` to `^8.2.0` ([#7857](https://github.com/MetaMask/core/pull/7857))
@@ -13,7 +13,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
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, _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_shouldHideNativeToken, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
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");
@@ -815,10 +815,6 @@ async function _AssetsController_updateState(response) {
815
815
  continue;
816
816
  }
817
817
  const assetChainId = extractChainId(typedAssetId);
818
- // Skip native tokens on Tempo networks
819
- if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_shouldHideNativeToken).call(this, assetChainId, typedAssetId, metadata)) {
820
- continue;
821
- }
822
818
  if (!chainIdSet.has(assetChainId)) {
823
819
  continue;
824
820
  }
@@ -852,18 +848,6 @@ async function _AssetsController_updateState(response) {
852
848
  }
853
849
  }
854
850
  return result;
855
- }, _AssetsController_shouldHideNativeToken = function _AssetsController_shouldHideNativeToken(chainId, assetId, metadata) {
856
- const TEMPO_CHAIN_IDS = ['eip155:42431', 'eip155:4217']; // Tempo Testnet (42431) and Mainnet (4217)
857
- // Check if it's a Tempo network
858
- if (!TEMPO_CHAIN_IDS.includes(chainId)) {
859
- return false;
860
- }
861
- // Check if it's a native token (either by metadata type or assetId format)
862
- const isNative = metadata.type === 'native' || assetId.includes('/slip44:');
863
- if (isNative) {
864
- return true;
865
- }
866
- return false;
867
851
  }, _AssetsController_tokenStandardToAssetType = function _AssetsController_tokenStandardToAssetType(tokenStandard) {
868
852
  switch (tokenStandard) {
869
853
  case 'native':
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsController.cjs","sourceRoot":"","sources":["../src/AssetsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n} from '@metamask/account-tree-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n ApiPlatformClient,\n BackendWebSocketServiceActions,\n BackendWebSocketServiceEvents,\n} from '@metamask/core-backend';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkEnablementControllerGetStateAction,\n NetworkEnablementControllerEvents,\n NetworkEnablementControllerState,\n} from '@metamask/network-enablement-controller';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BigNumberJS from 'bignumber.js';\nimport { isEqual } from 'lodash';\n\nimport type { AssetsControllerMethodActions } from './AssetsController-method-action-types';\nimport type {\n AbstractDataSource,\n DataSourceState,\n SubscriptionRequest,\n} from './data-sources/AbstractDataSource';\nimport { AccountsApiDataSource } from './data-sources/AccountsApiDataSource';\nimport { BackendWebsocketDataSource } from './data-sources/BackendWebsocketDataSource';\nimport { PriceDataSource } from './data-sources/PriceDataSource';\nimport type { RpcDataSourceConfig } from './data-sources/RpcDataSource';\nimport { RpcDataSource } from './data-sources/RpcDataSource';\nimport { SnapDataSource } from './data-sources/SnapDataSource';\nimport { TokenDataSource } from './data-sources/TokenDataSource';\nimport { projectLogger, createModuleLogger } from './logger';\nimport { DetectionMiddleware } from './middlewares/DetectionMiddleware';\nimport type {\n AccountId,\n AssetPreferences,\n ChainId,\n Caip19AssetId,\n AssetMetadata,\n AssetPrice,\n AssetBalance,\n AccountWithSupportedChains,\n AssetType,\n DataType,\n DataRequest,\n DataResponse,\n NextFunction,\n Middleware,\n SubscriptionResponse,\n Asset,\n AssetsControllerStateInternal,\n} from './types';\nimport { normalizeAssetId } from './utils';\n\n// ============================================================================\n// CONTROLLER CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'AssetsController' as const;\n\n/** Method names exposed as messenger actions (AssetsController:getAssets, etc.) */\nconst MESSENGER_EXPOSED_METHODS = [\n 'getAssets',\n 'getAssetsBalance',\n 'getAssetMetadata',\n 'getAssetsPrice',\n 'addCustomAsset',\n 'removeCustomAsset',\n 'getCustomAssets',\n 'hideAsset',\n 'unhideAsset',\n] as const;\n\n/** Default polling interval hint for data sources (30 seconds) */\nconst DEFAULT_POLLING_INTERVAL_MS = 30_000;\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// STATE TYPES\n// ============================================================================\n\n/**\n * State structure for AssetsController.\n *\n * All values are JSON-serializable. UI preferences (e.g. hidden) are in\n * assetPreferences, not in metadata.\n *\n * @see AssetsControllerStateInternal for the semantic type structure\n */\nexport type AssetsControllerState = {\n /** Shared metadata for all assets (stored once per asset) */\n assetsMetadata: { [assetId: string]: AssetMetadata };\n /** Per-account balance data */\n assetsBalance: { [accountId: string]: { [assetId: string]: AssetBalance } };\n /** Price data for assets */\n assetsPrice: { [assetId: string]: AssetPrice };\n /** Custom assets added by users per account (CAIP-19 asset IDs) */\n customAssets: { [accountId: string]: Caip19AssetId[] };\n /** UI preferences per asset (e.g. hidden) */\n assetPreferences: { [assetId: string]: AssetPreferences };\n};\n\n/**\n * Returns the default state for AssetsController.\n *\n * @returns The default AssetsController state with empty maps.\n */\nexport function getDefaultAssetsControllerState(): AssetsControllerState {\n return {\n assetsMetadata: {},\n assetsBalance: {},\n assetsPrice: {},\n customAssets: {},\n assetPreferences: {},\n };\n}\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\nexport type AssetsControllerGetStateAction = ControllerGetStateAction<\n typeof CONTROLLER_NAME,\n AssetsControllerState\n>;\n\nexport type AssetsControllerActions =\n | AssetsControllerGetStateAction\n | AssetsControllerMethodActions;\n\nexport type AssetsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof CONTROLLER_NAME,\n AssetsControllerState\n>;\n\nexport type AssetsControllerBalanceChangedEvent = {\n type: `${typeof CONTROLLER_NAME}:balanceChanged`;\n payload: [\n {\n accountId: AccountId;\n assetId: Caip19AssetId;\n previousAmount: string;\n newAmount: string;\n },\n ];\n};\n\nexport type AssetsControllerPriceChangedEvent = {\n type: `${typeof CONTROLLER_NAME}:priceChanged`;\n payload: [{ prices: Record<Caip19AssetId, AssetPrice> }];\n};\n\nexport type AssetsControllerAssetsDetectedEvent = {\n type: `${typeof CONTROLLER_NAME}:assetsDetected`;\n payload: [{ accountId: AccountId; assetIds: Caip19AssetId[] }];\n};\n\nexport type AssetsControllerEvents =\n | AssetsControllerStateChangeEvent\n | AssetsControllerBalanceChangedEvent\n | AssetsControllerPriceChangedEvent\n | AssetsControllerAssetsDetectedEvent;\n\ntype AllowedActions =\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | NetworkEnablementControllerGetStateAction\n // BackendWebsocketDataSource calls BackendWebSocketService\n | BackendWebSocketServiceActions;\n\ntype AllowedEvents =\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | NetworkEnablementControllerEvents\n | BackendWebSocketServiceEvents\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent;\n\nexport type AssetsControllerMessenger = Messenger<\n typeof CONTROLLER_NAME,\n AssetsControllerActions | AllowedActions,\n AssetsControllerEvents | AllowedEvents\n>;\n\n// ============================================================================\n// CONTROLLER OPTIONS\n// ============================================================================\n\nexport type AssetsControllerOptions = {\n messenger: AssetsControllerMessenger;\n state?: Partial<AssetsControllerState>;\n /** Default polling interval hint passed to data sources (ms) */\n defaultUpdateInterval?: number;\n /** Function to determine if the controller is enabled. Defaults to true. */\n isEnabled?: () => boolean;\n /**\n * API client for balance/price/metadata. The controller instantiates data sources\n * and uses them directly when this is provided.\n */\n queryApiClient: ApiPlatformClient;\n /** Optional configuration for RpcDataSource. */\n rpcDataSourceConfig?: RpcDataSourceConfig;\n};\n\n// ============================================================================\n// STATE METADATA\n// ============================================================================\n\nconst stateMetadata: StateMetadata<AssetsControllerState> = {\n assetsMetadata: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetsBalance: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetsPrice: {\n persist: false,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n customAssets: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetPreferences: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\nfunction extractChainId(assetId: Caip19AssetId): ChainId {\n const parsed = parseCaipAssetType(assetId);\n return parsed.chainId;\n}\n\n/**\n * Normalizes all asset IDs in a DataResponse.\n * This is applied at the controller level to ensure consistent state\n * regardless of how data sources format their asset IDs.\n *\n * @param response - The DataResponse to normalize.\n * @returns The normalized DataResponse with checksummed EVM addresses.\n */\nfunction normalizeResponse(response: DataResponse): DataResponse {\n const normalized: DataResponse = {};\n\n if (response.assetsMetadata) {\n normalized.assetsMetadata = {};\n for (const [assetId, metadata] of Object.entries(response.assetsMetadata)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsMetadata[normalizedId] = metadata;\n }\n }\n\n if (response.assetsPrice) {\n normalized.assetsPrice = {};\n for (const [assetId, price] of Object.entries(response.assetsPrice)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsPrice[normalizedId] = price;\n }\n }\n\n if (response.assetsBalance) {\n normalized.assetsBalance = {};\n for (const [accountId, balances] of Object.entries(\n response.assetsBalance,\n )) {\n normalized.assetsBalance[accountId] = {};\n for (const [assetId, balance] of Object.entries(balances)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsBalance[accountId][normalizedId] = balance;\n }\n }\n }\n\n // Preserve detectedAssets with normalized asset IDs\n if (response.detectedAssets) {\n normalized.detectedAssets = {};\n for (const [accountId, assetIds] of Object.entries(\n response.detectedAssets,\n )) {\n normalized.detectedAssets[accountId] = assetIds.map((assetId) =>\n normalizeAssetId(assetId),\n );\n }\n }\n\n // Preserve errors (chain IDs don't need normalization)\n if (response.errors) {\n normalized.errors = { ...response.errors };\n }\n\n return normalized;\n}\n\n// ============================================================================\n// CONTROLLER IMPLEMENTATION\n// ============================================================================\n\n/**\n * AssetsController provides a unified interface for managing asset balances\n * across all blockchain networks (EVM and non-EVM) and all asset types.\n *\n * ## Core Responsibilities\n *\n * 1. **One-Time Fetch (Sync)**: For initial load, force refresh, or on-demand queries.\n * Uses `getAssets()`, `getAssetsBalance()`, etc. with `forceUpdate: true`.\n *\n * 2. **Async Subscriptions**: Subscribes to data sources for ongoing updates.\n * Data sources push updates via callbacks; the controller updates state.\n *\n * 3. **Dynamic Source Selection**: Routes requests to appropriate data sources\n * based on which chains they support. When active chains change, the controller\n * dynamically adjusts subscriptions.\n *\n * 4. **Keyring Lifecycle**: Listens to KeyringController unlock/lock events to\n * start/stop subscriptions when the wallet is unlocked or locked.\n *\n * ## Architecture\n *\n * - Data sources declare their supported chains (async, can change over time)\n * - Data sources are responsible for their own update mechanisms (WebSocket, polling, events)\n * - The controller does NOT manage polling - it simply receives pushed updates\n */\nexport class AssetsController extends BaseController<\n typeof CONTROLLER_NAME,\n AssetsControllerState,\n AssetsControllerMessenger\n> {\n /** Whether the controller is enabled */\n readonly #isEnabled: boolean;\n\n /** Default update interval hint passed to data sources */\n readonly #defaultUpdateInterval: number;\n\n readonly #controllerMutex = new Mutex();\n\n /**\n * Active balance subscriptions keyed by account ID.\n * Each account has one logical subscription that may span multiple data sources.\n * For example, if WebSocket covers chains A,B and RPC covers chain C,\n * the account subscribes to both data sources for its chains.\n */\n readonly #activeSubscriptions: Map<string, SubscriptionResponse> = new Map();\n\n /** Currently enabled chains from NetworkEnablementController */\n #enabledChains: Set<ChainId> = new Set();\n\n /**\n * Get the currently selected accounts from AccountTreeController.\n * This includes all accounts in the same group as the selected account\n * (EVM, Bitcoin, Solana, Tron, etc. that belong to the same logical account group).\n *\n * @returns Array of InternalAccount objects from the selected account group.\n */\n get #selectedAccounts(): InternalAccount[] {\n return this.messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n }\n\n readonly #backendWebsocketDataSource: BackendWebsocketDataSource;\n\n readonly #accountsApiDataSource: AccountsApiDataSource;\n\n readonly #snapDataSource: SnapDataSource;\n\n readonly #rpcDataSource: RpcDataSource;\n\n /**\n * Subscription balance data sources in assignment priority order (first that supports a chain gets it).\n *\n * @returns The four balance data source instances in priority order.\n */\n get #subscriptionBalanceDataSources(): [\n BackendWebsocketDataSource,\n AccountsApiDataSource,\n SnapDataSource,\n RpcDataSource,\n ] {\n return [\n this.#backendWebsocketDataSource,\n this.#accountsApiDataSource,\n this.#snapDataSource,\n this.#rpcDataSource,\n ];\n }\n\n readonly #priceDataSource: PriceDataSource;\n\n readonly #detectionMiddleware: DetectionMiddleware;\n\n readonly #tokenDataSource: TokenDataSource;\n\n constructor({\n messenger,\n state = {},\n defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS,\n isEnabled = (): boolean => true,\n queryApiClient,\n rpcDataSourceConfig,\n }: AssetsControllerOptions) {\n super({\n name: CONTROLLER_NAME,\n messenger,\n metadata: stateMetadata,\n state: {\n ...getDefaultAssetsControllerState(),\n ...state,\n },\n });\n\n this.#isEnabled = isEnabled();\n this.#defaultUpdateInterval = defaultUpdateInterval;\n const rpcConfig = rpcDataSourceConfig ?? {};\n\n const onActiveChainsUpdated = (\n dataSourceName: string,\n chains: ChainId[],\n previousChains: ChainId[],\n ): void =>\n this.handleActiveChainsUpdate(dataSourceName, chains, previousChains);\n\n this.#backendWebsocketDataSource = new BackendWebsocketDataSource({\n messenger: this.messenger,\n queryApiClient,\n onActiveChainsUpdated,\n });\n this.#accountsApiDataSource = new AccountsApiDataSource({\n queryApiClient,\n onActiveChainsUpdated,\n });\n this.#snapDataSource = new SnapDataSource({\n messenger: this.messenger,\n onActiveChainsUpdated,\n });\n this.#rpcDataSource = new RpcDataSource({\n messenger: this.messenger,\n onActiveChainsUpdated,\n ...rpcConfig,\n });\n this.#tokenDataSource = new TokenDataSource({\n queryApiClient,\n });\n this.#priceDataSource = new PriceDataSource({\n queryApiClient,\n });\n this.#detectionMiddleware = new DetectionMiddleware();\n\n if (!this.#isEnabled) {\n log('AssetsController is disabled, skipping initialization');\n return;\n }\n\n log('Initializing AssetsController', {\n defaultUpdateInterval: this.#defaultUpdateInterval,\n });\n\n this.#initializeState();\n this.#subscribeToEvents();\n this.#registerActionHandlers();\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n #initializeState(): void {\n const { enabledNetworkMap } = this.messenger.call(\n 'NetworkEnablementController:getState',\n );\n this.#enabledChains = this.#extractEnabledChains(enabledNetworkMap);\n\n log('Initialized state', {\n enabledNetworkMap,\n enabledChains: this.#enabledChains,\n });\n }\n\n /**\n * Extract enabled chains from enabledNetworkMap.\n * Returns CAIP-2 chain IDs for all enabled networks across all namespaces.\n *\n * Note: For EIP155 (EVM) chains, the reference is normalized to decimal format\n * to ensure consistency with CAIP-2 standard and API responses.\n *\n * @param enabledNetworkMap - The enabled network map from NetworkEnablementController.\n * @returns Set of CAIP-2 chain IDs for all enabled networks.\n */\n #extractEnabledChains(\n enabledNetworkMap: NetworkEnablementControllerState['enabledNetworkMap'],\n ): Set<ChainId> {\n const chains = new Set<ChainId>();\n\n for (const [namespace, networks] of Object.entries(enabledNetworkMap)) {\n for (const [reference, isEnabled] of Object.entries(networks)) {\n if (isEnabled) {\n // Check if reference is already a full CAIP-2 chain ID (contains colon)\n if (reference.includes(':')) {\n // Already a full chain ID, use as-is\n chains.add(reference as ChainId);\n } else {\n // Normalize EIP155 chain references from hex to decimal (CAIP-2 standard)\n const normalizedReference = this.#normalizeChainReference(\n namespace,\n reference,\n );\n chains.add(`${namespace}:${normalizedReference}`);\n }\n }\n }\n }\n return chains;\n }\n\n /**\n * Normalize chain reference to CAIP-2 standard format.\n * For EIP155, converts hex chain IDs to decimal.\n *\n * @param namespace - The chain namespace (e.g., \"eip155\").\n * @param reference - The chain reference (e.g., \"0x1\" or \"1\").\n * @returns The normalized chain reference in decimal format.\n */\n #normalizeChainReference(namespace: string, reference: string): string {\n if (namespace === 'eip155' && reference.startsWith('0x')) {\n // Convert hex to decimal for EIP155 chains\n return parseInt(reference, 16).toString();\n }\n return reference;\n }\n\n #subscribeToEvents(): void {\n // Subscribe to account group changes (when user switches between account groups like Account 1 -> Account 2)\n this.messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n () => {\n this.#handleAccountGroupChanged().catch(console.error);\n },\n );\n\n // Subscribe to network enablement changes (only enabledNetworkMap)\n this.messenger.subscribe(\n 'NetworkEnablementController:stateChange',\n ({ enabledNetworkMap }) => {\n this.#handleEnabledNetworksChanged(enabledNetworkMap).catch(\n console.error,\n );\n },\n );\n\n // Keyring lifecycle: start when unlocked, stop when locked\n this.messenger.subscribe('KeyringController:unlock', () => this.#start());\n this.messenger.subscribe('KeyringController:lock', () => this.#stop());\n }\n\n #registerActionHandlers(): void {\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n // ============================================================================\n // DATA SOURCE CHAIN MANAGEMENT\n // ============================================================================\n\n /**\n * Handle when a data source's supported chains change.\n * Used to refresh balance subscriptions and run a one-time fetch when a new chain is supported.\n *\n * - On any add/remove: re-subscribes to data sources so chain assignment stays correct.\n * - When chains are added: fetches balances for the new chains (for selected accounts on enabled networks).\n *\n * Controller does not store chains; sources report via this callback. previousChains is required for diff.\n *\n * @param dataSourceId - The identifier of the data source reporting the change.\n * @param activeChains - Currently active (supported and available) chain IDs for this source.\n * @param previousChains - Previous chains; used to compute added/removed.\n */\n handleActiveChainsUpdate(\n dataSourceId: string,\n activeChains: ChainId[],\n previousChains: ChainId[],\n ): void {\n log('Data source active chains changed', {\n dataSourceId,\n chainCount: activeChains.length,\n chains: activeChains,\n });\n\n const previous: ChainId[] = previousChains;\n\n const previousSet = new Set(previous);\n const addedChains = activeChains.filter((ch) => !previousSet.has(ch));\n const removedChains = previous.filter((ch) => !activeChains.includes(ch));\n\n if (addedChains.length > 0 || removedChains.length > 0) {\n // Refresh subscriptions to use updated data source availability\n this.#subscribeAssets();\n }\n\n // If chains were added and we have selected accounts, do one-time fetch\n if (addedChains.length > 0 && this.#selectedAccounts.length > 0) {\n const addedEnabledChains = addedChains.filter((chain) =>\n this.#enabledChains.has(chain),\n );\n if (addedEnabledChains.length > 0) {\n log('Fetching balances for newly added chains', { addedEnabledChains });\n this.getAssets(this.#selectedAccounts, {\n chainIds: addedEnabledChains,\n forceUpdate: true,\n }).catch((error) => {\n log('Failed to fetch balance for added chains', { error });\n });\n }\n }\n }\n\n // ============================================================================\n // MIDDLEWARE EXECUTION\n // ============================================================================\n\n /**\n * Execute middlewares with request/response context.\n *\n * @param middlewares - Middlewares to execute in order.\n * @param request - The data request.\n * @param initialResponse - Optional initial response (for enriching existing data).\n * @returns The final DataResponse after all middlewares have processed.\n */\n async #executeMiddlewares(\n middlewares: Middleware[],\n request: DataRequest,\n initialResponse: DataResponse = {},\n ): Promise<DataResponse> {\n const chain = middlewares.reduceRight<NextFunction>(\n (next, middleware) =>\n async (\n ctx,\n ): Promise<{\n request: DataRequest;\n response: DataResponse;\n getAssetsState: () => AssetsControllerStateInternal;\n }> => {\n try {\n return await middleware(ctx, next);\n } catch (error) {\n console.error('[AssetsController] Middleware failed:', error);\n return next(ctx);\n }\n },\n async (ctx) => ctx,\n );\n\n const result = await chain({\n request,\n response: initialResponse,\n getAssetsState: () => this.state as AssetsControllerStateInternal,\n });\n return result.response;\n }\n\n // ============================================================================\n // PUBLIC API: QUERY METHODS\n // ============================================================================\n\n async getAssets(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n dataTypes?: DataType[];\n },\n ): Promise<Record<AccountId, Record<Caip19AssetId, Asset>>> {\n const chainIds = options?.chainIds ?? [...this.#enabledChains];\n const assetTypes = options?.assetTypes ?? ['fungible'];\n const dataTypes = options?.dataTypes ?? ['balance', 'metadata', 'price'];\n\n // Collect custom assets for all requested accounts\n const customAssets: Caip19AssetId[] = [];\n for (const account of accounts) {\n const accountCustomAssets = this.getCustomAssets(account.id);\n customAssets.push(...accountCustomAssets);\n }\n\n if (options?.forceUpdate) {\n const request = this.#buildDataRequest(accounts, chainIds, {\n assetTypes,\n dataTypes,\n customAssets: customAssets.length > 0 ? customAssets : undefined,\n forceUpdate: true,\n });\n const response = await this.#executeMiddlewares(\n [\n this.#accountsApiDataSource.assetsMiddleware,\n this.#snapDataSource.assetsMiddleware,\n this.#rpcDataSource.assetsMiddleware,\n this.#detectionMiddleware.assetsMiddleware,\n this.#tokenDataSource.assetsMiddleware,\n this.#priceDataSource.assetsMiddleware,\n ],\n request,\n );\n await this.#updateState(response);\n }\n\n return this.#getAssetsFromState(accounts, chainIds, assetTypes);\n }\n\n async getAssetsBalance(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n },\n ): Promise<Record<AccountId, Record<Caip19AssetId, AssetBalance>>> {\n // Reuse getAssets with dataTypes: ['balance'] only\n const assets = await this.getAssets(accounts, {\n chainIds: options?.chainIds,\n assetTypes: options?.assetTypes,\n forceUpdate: options?.forceUpdate,\n dataTypes: ['balance', 'metadata'],\n });\n\n // Extract just the balance from each asset\n const result: Record<AccountId, Record<Caip19AssetId, AssetBalance>> = {};\n for (const [accountId, accountAssets] of Object.entries(assets)) {\n result[accountId] = {};\n for (const [assetId, asset] of Object.entries(accountAssets)) {\n if (asset.balance) {\n result[accountId][assetId as Caip19AssetId] = asset.balance;\n }\n }\n }\n\n return result;\n }\n\n getAssetMetadata(assetId: Caip19AssetId): AssetMetadata | undefined {\n return this.state.assetsMetadata[assetId] as AssetMetadata | undefined;\n }\n\n async getAssetsPrice(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n },\n ): Promise<Record<Caip19AssetId, AssetPrice>> {\n const assets = await this.getAssets(accounts, {\n chainIds: options?.chainIds,\n assetTypes: options?.assetTypes,\n forceUpdate: options?.forceUpdate,\n dataTypes: ['price'],\n });\n\n // Extract just the price from each asset (flattened across accounts)\n const result: Record<Caip19AssetId, AssetPrice> = {};\n for (const accountAssets of Object.values(assets)) {\n for (const [assetId, asset] of Object.entries(accountAssets)) {\n if (asset.price) {\n result[assetId as Caip19AssetId] = asset.price;\n }\n }\n }\n\n return result;\n }\n\n // ============================================================================\n // CUSTOM ASSETS MANAGEMENT\n // ============================================================================\n\n /**\n * Add a custom asset for an account.\n * Custom assets are included in subscription and fetch operations.\n * Adding a custom asset also unhides it if it was previously hidden.\n *\n * @param accountId - The account ID to add the custom asset for.\n * @param assetId - The CAIP-19 asset ID to add.\n */\n async addCustomAsset(\n accountId: AccountId,\n assetId: Caip19AssetId,\n ): Promise<void> {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Adding custom asset', { accountId, assetId: normalizedAssetId });\n\n this.update((state) => {\n const customAssets = state.customAssets as Record<string, string[]>;\n if (!customAssets[accountId]) {\n customAssets[accountId] = [];\n }\n\n // Only add if not already present\n if (!customAssets[accountId].includes(normalizedAssetId)) {\n customAssets[accountId].push(normalizedAssetId);\n }\n\n // Unhide the asset if it was hidden (via assetPreferences)\n const prefs = state.assetPreferences[normalizedAssetId];\n if (prefs?.hidden) {\n delete prefs.hidden;\n if (Object.keys(prefs).length === 0) {\n delete state.assetPreferences[normalizedAssetId];\n }\n }\n });\n\n // Fetch data for the newly added custom asset\n const account = this.#selectedAccounts.find((a) => a.id === accountId);\n if (account) {\n const chainId = extractChainId(normalizedAssetId);\n await this.getAssets([account], {\n chainIds: [chainId],\n forceUpdate: true,\n });\n }\n }\n\n /**\n * Remove a custom asset from an account.\n *\n * @param accountId - The account ID to remove the custom asset from.\n * @param assetId - The CAIP-19 asset ID to remove.\n */\n removeCustomAsset(accountId: AccountId, assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Removing custom asset', { accountId, assetId: normalizedAssetId });\n\n this.update((state) => {\n if (state.customAssets[accountId]) {\n state.customAssets[accountId] = state.customAssets[accountId].filter(\n (id) => id !== normalizedAssetId,\n );\n\n // Clean up empty arrays\n if (state.customAssets[accountId].length === 0) {\n delete state.customAssets[accountId];\n }\n }\n });\n }\n\n /**\n * Get all custom assets for an account.\n *\n * @param accountId - The account ID to get custom assets for.\n * @returns Array of CAIP-19 asset IDs for the account's custom assets.\n */\n getCustomAssets(accountId: AccountId): Caip19AssetId[] {\n return this.state.customAssets[accountId] ?? [];\n }\n\n // ============================================================================\n // HIDDEN ASSETS MANAGEMENT\n // ============================================================================\n\n /**\n * Hide an asset globally.\n * Hidden assets are excluded from the asset list returned by getAssets.\n * The hidden state is stored in assetPreferences.\n *\n * @param assetId - The CAIP-19 asset ID to hide.\n */\n hideAsset(assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Hiding asset', { assetId: normalizedAssetId });\n\n this.update((state) => {\n if (!state.assetPreferences[normalizedAssetId]) {\n state.assetPreferences[normalizedAssetId] = {};\n }\n state.assetPreferences[normalizedAssetId].hidden = true;\n });\n }\n\n /**\n * Unhide an asset globally.\n *\n * @param assetId - The CAIP-19 asset ID to unhide.\n */\n unhideAsset(assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Unhiding asset', { assetId: normalizedAssetId });\n\n this.update((state) => {\n const prefs = state.assetPreferences[normalizedAssetId];\n if (prefs) {\n delete prefs.hidden;\n if (Object.keys(prefs).length === 0) {\n delete state.assetPreferences[normalizedAssetId];\n }\n }\n });\n }\n\n // ============================================================================\n // SUBSCRIPTIONS\n // ============================================================================\n\n /**\n * Subscribe to price updates for all assets held by the given accounts.\n * Polls PriceDataSource which fetches prices from balance state.\n *\n * @param accounts - Accounts to subscribe price updates for.\n * @param chainIds - Chain IDs to filter prices for.\n * @param options - Subscription options.\n * @param options.updateInterval - Polling interval in ms.\n */\n subscribeAssetsPrice(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n options: { updateInterval?: number } = {},\n ): void {\n const { updateInterval = this.#defaultUpdateInterval } = options;\n const subscriptionKey = 'ds:PriceDataSource';\n\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n const isUpdate = existingSubscription !== undefined;\n\n const subscribeReq: SubscriptionRequest = {\n request: this.#buildDataRequest(accounts, chainIds, {\n dataTypes: ['price'],\n updateInterval,\n }),\n subscriptionId: subscriptionKey,\n isUpdate,\n onAssetsUpdate: (response) =>\n this.handleAssetsUpdate(response, 'PriceDataSource'),\n getAssetsState: () => this.state,\n };\n\n this.#priceDataSource.subscribe(subscribeReq).catch(console.error);\n\n // Track subscription\n const subscription: SubscriptionResponse = {\n chains: chainIds,\n accountId: subscriptionKey,\n assetTypes: ['fungible'],\n dataTypes: ['price'],\n unsubscribe: () => {\n this.#activeSubscriptions.delete(subscriptionKey);\n },\n };\n\n this.#activeSubscriptions.set(subscriptionKey, subscription);\n }\n\n /**\n * Unsubscribe from price updates.\n */\n unsubscribeAssetsPrice(): void {\n const subscriptionKey = 'ds:PriceDataSource';\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n\n if (!existingSubscription) {\n return;\n }\n this.#priceDataSource.unsubscribe(subscriptionKey).catch(console.error);\n existingSubscription.unsubscribe();\n }\n\n // ============================================================================\n // STATE MANAGEMENT\n // ============================================================================\n\n async #updateState(response: DataResponse): Promise<void> {\n // Normalize asset IDs (checksum EVM addresses) before storing in state\n const normalizedResponse = normalizeResponse(response);\n\n const releaseLock = await this.#controllerMutex.acquire();\n\n try {\n const previousState = this.state;\n const previousPrices = { ...this.state.assetsPrice };\n // Use detectedAssets from response (assets without metadata)\n const detectedAssets: Record<AccountId, Caip19AssetId[]> =\n normalizedResponse.detectedAssets ?? {};\n\n // Track actual changes for logging\n const changedBalances: {\n accountId: string;\n assetId: string;\n oldAmount: string | undefined;\n newAmount: string;\n }[] = [];\n const changedMetadata: string[] = [];\n\n this.update((state) => {\n // Use type assertions to avoid deep type instantiation issues with Immer Draft types\n const metadata = state.assetsMetadata as Record<string, AssetMetadata>;\n const balances = state.assetsBalance as Record<\n string,\n Record<string, AssetBalance>\n >;\n const prices = state.assetsPrice as Record<string, AssetPrice>;\n\n if (normalizedResponse.assetsMetadata) {\n for (const [key, value] of Object.entries(\n normalizedResponse.assetsMetadata,\n )) {\n if (\n !isEqual(\n previousState.assetsMetadata[key as Caip19AssetId],\n value,\n )\n ) {\n changedMetadata.push(key);\n }\n metadata[key] = value;\n }\n }\n\n if (normalizedResponse.assetsBalance) {\n for (const [accountId, accountBalances] of Object.entries(\n normalizedResponse.assetsBalance,\n )) {\n const previousBalances =\n previousState.assetsBalance[accountId] ?? {};\n\n if (!balances[accountId]) {\n balances[accountId] = {};\n }\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n const previousBalance = previousBalances[\n assetId as Caip19AssetId\n ] as { amount: string } | undefined;\n const balanceData = balance as { amount: string };\n const newAmount = balanceData.amount;\n const oldAmount = previousBalance?.amount;\n\n // Track if balance actually changed\n if (oldAmount !== newAmount) {\n changedBalances.push({\n accountId,\n assetId,\n oldAmount,\n newAmount,\n });\n }\n }\n\n Object.assign(balances[accountId], accountBalances);\n }\n }\n\n // Update prices in state\n if (normalizedResponse.assetsPrice) {\n for (const [key, value] of Object.entries(\n normalizedResponse.assetsPrice,\n )) {\n prices[key] = value;\n }\n }\n });\n\n // Calculate changed prices\n const changedPriceAssets: string[] = normalizedResponse.assetsPrice\n ? Object.keys(normalizedResponse.assetsPrice).filter(\n (assetId) =>\n !isEqual(\n previousPrices[assetId as Caip19AssetId],\n normalizedResponse.assetsPrice?.[assetId as Caip19AssetId],\n ),\n )\n : [];\n\n // Log only actual changes\n if (\n changedBalances.length > 0 ||\n changedMetadata.length > 0 ||\n changedPriceAssets.length > 0\n ) {\n log('State updated', {\n changedBalances:\n changedBalances.length > 0 ? changedBalances : undefined,\n changedMetadataCount:\n changedMetadata.length > 0 ? changedMetadata.length : undefined,\n changedPricesCount:\n changedPriceAssets.length > 0\n ? changedPriceAssets.length\n : undefined,\n newAssets:\n Object.keys(detectedAssets).length > 0\n ? Object.entries(detectedAssets).map(([accountId, assets]) => ({\n accountId,\n assets,\n }))\n : undefined,\n });\n }\n\n // Publish balance changed events\n for (const change of changedBalances) {\n this.messenger.publish('AssetsController:balanceChanged', {\n accountId: change.accountId,\n assetId: change.assetId as Caip19AssetId,\n previousAmount: change.oldAmount ?? '0',\n newAmount: change.newAmount,\n });\n }\n\n // Publish price changed event with full price data\n if (changedPriceAssets.length > 0 && normalizedResponse.assetsPrice) {\n // Build prices object with only changed prices\n const changedPrices: Record<Caip19AssetId, AssetPrice> = {};\n for (const assetId of changedPriceAssets) {\n const price =\n normalizedResponse.assetsPrice[assetId as Caip19AssetId];\n if (price) {\n changedPrices[assetId as Caip19AssetId] = price;\n }\n }\n this.messenger.publish('AssetsController:priceChanged', {\n prices: changedPrices,\n });\n }\n\n // Publish assets detected events\n for (const [accountId, assetIds] of Object.entries(detectedAssets)) {\n if (assetIds.length > 0) {\n this.messenger.publish('AssetsController:assetsDetected', {\n accountId,\n assetIds,\n });\n }\n }\n } finally {\n releaseLock();\n }\n }\n\n #getAssetsFromState(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n assetTypes: AssetType[],\n ): Record<AccountId, Record<Caip19AssetId, Asset>> {\n const result: Record<AccountId, Record<Caip19AssetId, Asset>> = {};\n // Convert to Sets for O(1) lookups\n const chainIdSet = new Set(chainIds);\n const assetTypeSet = new Set(assetTypes);\n\n for (const account of accounts) {\n result[account.id] = {};\n\n const accountBalances = this.state.assetsBalance[account.id] ?? {};\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n const typedAssetId = assetId as Caip19AssetId;\n\n const metadataRaw = this.state.assetsMetadata[typedAssetId];\n\n // Skip assets without metadata\n if (!metadataRaw) {\n continue;\n }\n\n const metadata = metadataRaw;\n\n // Skip hidden assets (assetPreferences)\n const prefs = this.state.assetPreferences[typedAssetId];\n if (prefs?.hidden) {\n continue;\n }\n\n const assetChainId = extractChainId(typedAssetId);\n\n // Skip native tokens on Tempo networks\n if (this.#shouldHideNativeToken(assetChainId, typedAssetId, metadata)) {\n continue;\n }\n\n if (!chainIdSet.has(assetChainId)) {\n continue;\n }\n\n // Filter by asset type\n const tokenAssetType = this.#tokenStandardToAssetType(metadata.type);\n if (!assetTypeSet.has(tokenAssetType)) {\n continue;\n }\n\n const typedBalance = balance;\n const priceRaw = this.state.assetsPrice[typedAssetId];\n const price: AssetPrice = priceRaw ?? {\n price: 0,\n lastUpdated: 0,\n };\n\n // Compute fiat value using BigNumber for precision\n // Note: typedBalance.amount is already in human-readable format (e.g., \"1\" for 1 ETH)\n // so we do NOT divide by 10^decimals here\n const balanceAmount = new BigNumberJS(typedBalance.amount || '0');\n const fiatValue = balanceAmount\n .multipliedBy(price.price || 0)\n .toNumber();\n\n const asset: Asset = {\n id: typedAssetId,\n chainId: assetChainId,\n balance: typedBalance,\n metadata,\n price,\n fiatValue,\n };\n\n result[account.id][typedAssetId] = asset;\n }\n }\n\n return result;\n }\n\n /**\n * Determines if a native token should be hidden on specific networks.\n *\n * @param chainId - The CAIP-2 chain ID (e.g., \"eip155:42431\").\n * @param assetId - The CAIP-19 asset ID (e.g., \"eip155:42431/slip44:60\").\n * @param metadata - The asset metadata.\n * @returns True if the token should be hidden, false otherwise.\n */\n #shouldHideNativeToken(\n chainId: ChainId,\n assetId: Caip19AssetId,\n metadata: AssetMetadata,\n ): boolean {\n const TEMPO_CHAIN_IDS = ['eip155:42431', 'eip155:4217']; // Tempo Testnet (42431) and Mainnet (4217)\n\n // Check if it's a Tempo network\n if (!TEMPO_CHAIN_IDS.includes(chainId)) {\n return false;\n }\n\n // Check if it's a native token (either by metadata type or assetId format)\n const isNative =\n metadata.type === 'native' || assetId.includes('/slip44:');\n\n if (isNative) {\n return true;\n }\n\n\n return false;\n }\n\n /**\n * Maps a token standard to its corresponding asset type.\n *\n * @param tokenStandard - The token standard from metadata.\n * @returns The corresponding asset type.\n */\n #tokenStandardToAssetType(tokenStandard: string): AssetType {\n switch (tokenStandard) {\n case 'native':\n case 'erc20':\n case 'spl':\n return 'fungible';\n case 'erc721':\n return 'nft';\n case 'erc1155':\n // ERC1155 can be either fungible or non-fungible, treat as collectible\n return 'collectible';\n default:\n // Unknown standards default to fungible\n return 'fungible';\n }\n }\n\n // ============================================================================\n // START / STOP\n // ============================================================================\n\n /**\n * Start asset tracking: subscribe to updates and fetch current balances.\n * Called when app opens, account changes, or keyring unlocks.\n */\n #start(): void {\n log('Starting asset tracking', {\n selectedAccountCount: this.#selectedAccounts.length,\n enabledChainCount: this.#enabledChains.size,\n });\n\n this.#subscribeAssets();\n if (this.#selectedAccounts.length > 0) {\n this.getAssets(this.#selectedAccounts, {\n chainIds: [...this.#enabledChains],\n forceUpdate: true,\n }).catch((error) => {\n log('Failed to fetch assets', error);\n });\n }\n }\n\n /**\n * Stop asset tracking: unsubscribe from all updates.\n * Called when app closes or keyring locks.\n */\n #stop(): void {\n log('Stopping asset tracking', {\n activeSubscriptionCount: this.#activeSubscriptions.size,\n hasPriceSubscription: this.#activeSubscriptions.has('ds:PriceDataSource'),\n });\n\n // Stop price subscription first (uses direct messenger call)\n this.unsubscribeAssetsPrice();\n\n // Stop balance subscriptions by properly notifying data sources via messenger\n // This ensures data sources stop their polling timers\n // Convert to array first to avoid modifying map during iteration\n const subscriptionKeys = [...this.#activeSubscriptions.keys()];\n for (const subscriptionKey of subscriptionKeys) {\n if (subscriptionKey.startsWith('ds:')) {\n const sourceId = subscriptionKey.slice(3);\n const source = this.#subscriptionBalanceDataSources.find(\n (ds) => ds.getName() === sourceId,\n );\n if (source) {\n this.#unsubscribeDataSource(source);\n }\n }\n }\n this.#activeSubscriptions.clear();\n }\n\n /**\n * Subscribe to asset updates for all selected accounts.\n */\n #subscribeAssets(): void {\n if (this.#selectedAccounts.length === 0) {\n return;\n }\n\n // Subscribe to balance updates (batched by data source)\n this.#subscribeAssetsBalance(this.#selectedAccounts, [\n ...this.#enabledChains,\n ]);\n\n // Subscribe to price updates for all assets held by selected accounts\n this.subscribeAssetsPrice(this.#selectedAccounts, [...this.#enabledChains]);\n }\n\n /**\n * Subscribe to balance updates for the given accounts and chains.\n *\n * Strategy to minimize data source calls:\n * 1. Collect all chains to subscribe based on enabled networks\n * 2. Map chains to accounts based on their scopes\n * 3. Split by data source (ordered by priority) - each data source gets ONE subscription\n *\n * This ensures we make minimal subscriptions to each data source while covering\n * all accounts and chains.\n *\n * @param accounts - Accounts to subscribe balance updates for.\n * @param chainIds - Chain IDs to subscribe for.\n */\n #subscribeAssetsBalance(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n ): void {\n const chainToAccounts = this.#buildChainToAccountsMap(\n accounts,\n new Set(chainIds),\n );\n const remainingChains = new Set(chainToAccounts.keys());\n\n for (const source of this.#subscriptionBalanceDataSources) {\n const availableChains = new Set(source.getActiveChainsSync());\n const assignedChains: ChainId[] = [];\n\n for (const chainId of remainingChains) {\n if (availableChains.has(chainId)) {\n assignedChains.push(chainId);\n remainingChains.delete(chainId);\n }\n }\n\n if (assignedChains.length === 0) {\n this.#unsubscribeDataSource(source);\n continue;\n }\n\n const seenIds = new Set<string>();\n const accountsForSource = assignedChains\n .flatMap((chainId) => chainToAccounts.get(chainId) ?? [])\n .filter(\n (account) =>\n !seenIds.has(account.id) && (seenIds.add(account.id), true),\n );\n if (accountsForSource.length > 0) {\n this.#subscribeDataSource(source, accountsForSource, assignedChains);\n }\n }\n }\n\n /**\n * Build a mapping of chainId -> accounts that support that chain.\n * Only includes chains that are in the chainsToSubscribe set.\n *\n * @param accounts - Array of accounts to build mapping for.\n * @param chainsToSubscribe - Set of chain IDs to include in the mapping.\n * @returns Map of chainId to array of accounts that support that chain.\n */\n #buildChainToAccountsMap(\n accounts: InternalAccount[],\n chainsToSubscribe: Set<ChainId>,\n ): Map<ChainId, InternalAccount[]> {\n const chainToAccounts = new Map<ChainId, InternalAccount[]>();\n for (const account of accounts) {\n for (const chainId of this.#getEnabledChainsForAccount(account)) {\n if (!chainsToSubscribe.has(chainId)) {\n continue;\n }\n let list = chainToAccounts.get(chainId);\n if (!list) {\n list = [];\n chainToAccounts.set(chainId, list);\n }\n list.push(account);\n }\n }\n return chainToAccounts;\n }\n\n /**\n * Subscribe to a specific data source with accounts and chains.\n * Uses the data source name as the subscription key for batching.\n *\n * @param source - The balance data source instance.\n * @param accounts - Array of accounts to subscribe for.\n * @param chains - Array of chain IDs to subscribe for.\n */\n #subscribeDataSource(\n source: AbstractDataSource<string, DataSourceState>,\n accounts: InternalAccount[],\n chains: ChainId[],\n ): void {\n const sourceId = source.getName();\n const subscriptionKey = `ds:${sourceId}`;\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n const isUpdate = existingSubscription !== undefined;\n\n log('Subscribe to data source', {\n sourceId,\n subscriptionKey,\n isUpdate,\n accountCount: accounts.length,\n chainCount: chains.length,\n });\n\n const subscribeReq: SubscriptionRequest = {\n request: this.#buildDataRequest(accounts, chains, {\n assetTypes: ['fungible'],\n dataTypes: ['balance'],\n updateInterval: this.#defaultUpdateInterval,\n }),\n subscriptionId: subscriptionKey,\n isUpdate,\n onAssetsUpdate: (response) => this.handleAssetsUpdate(response, sourceId),\n getAssetsState: () => this.state,\n };\n\n source.subscribe(subscribeReq).catch((error) => {\n console.error(\n `[AssetsController] Failed to subscribe to '${sourceId}':`,\n error,\n );\n });\n\n // Track subscription\n const subscription: SubscriptionResponse = {\n chains,\n accountId: subscriptionKey,\n assetTypes: ['fungible'],\n dataTypes: ['balance'],\n unsubscribe: () => {\n this.#activeSubscriptions.delete(subscriptionKey);\n },\n };\n\n this.#activeSubscriptions.set(subscriptionKey, subscription);\n }\n\n /**\n * Unsubscribe from a data source if we have an active subscription.\n *\n * @param source - The balance data source instance to unsubscribe from.\n */\n #unsubscribeDataSource(\n source: AbstractDataSource<string, DataSourceState>,\n ): void {\n const subscriptionKey = `ds:${source.getName()}`;\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n\n if (existingSubscription) {\n source.unsubscribe(subscriptionKey).catch(() => undefined);\n existingSubscription.unsubscribe();\n }\n }\n\n // ============================================================================\n // HELPERS\n // ============================================================================\n\n /**\n * Build a DataRequest with accountsWithSupportedChains (enabled chains ∩ account scope ∩ requested chainIds).\n *\n * @param accounts - Accounts to include.\n * @param chainIds - Requested chain IDs (e.g. enabled chains or subset).\n * @param partial - Rest of the request (dataTypes, assetTypes, etc.).\n * @returns DataRequest with accountsWithSupportedChains and chainIds.\n */\n #buildDataRequest(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n partial: Partial<\n Omit<DataRequest, 'accountsWithSupportedChains' | 'chainIds'>\n > = {},\n ): DataRequest {\n const chainIdSet = new Set(chainIds);\n const accountsWithSupportedChains: AccountWithSupportedChains[] =\n accounts.map((account) => ({\n account,\n supportedChains: this.#getEnabledChainsForAccount(account).filter(\n (chain) => chainIdSet.has(chain),\n ),\n }));\n return {\n accountsWithSupportedChains,\n chainIds,\n ...partial,\n } as DataRequest;\n }\n\n /**\n * Get the chains that an account supports based on its scopes.\n * Returns the intersection of the account's scopes and the enabled chains.\n *\n * @param account - The account to get supported chains for.\n * @returns Array of ChainIds that the account supports and are enabled.\n */\n #getEnabledChainsForAccount(account: InternalAccount): ChainId[] {\n // Account scopes are CAIP-2 chain IDs like \"eip155:1\", \"solana:mainnet\", \"bip122:...\"\n const scopes = account.scopes ?? [];\n const result: ChainId[] = [];\n\n for (const scope of scopes) {\n const [namespace, reference] = (scope as string).split(':');\n\n // Wildcard scope (e.g., \"eip155:0\" means all enabled chains in that namespace)\n if (reference === '0') {\n for (const chain of this.#enabledChains) {\n if (chain.startsWith(`${namespace}:`)) {\n result.push(chain);\n }\n }\n } else if (namespace === 'eip155' && reference?.startsWith('0x')) {\n // Normalize hex to decimal for EIP155\n result.push(`eip155:${parseInt(reference, 16)}` as ChainId);\n } else {\n result.push(scope);\n }\n }\n\n return result;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n async #handleAccountGroupChanged(): Promise<void> {\n const accounts = this.#selectedAccounts;\n\n log('Account group changed', {\n accountCount: accounts.length,\n accountIds: accounts.map((a) => a.id),\n });\n\n // Subscribe and fetch for the new account group\n this.#subscribeAssets();\n if (accounts.length > 0) {\n await this.getAssets(accounts, {\n chainIds: [...this.#enabledChains],\n forceUpdate: true,\n });\n }\n }\n\n async #handleEnabledNetworksChanged(\n enabledNetworkMap: NetworkEnablementControllerState['enabledNetworkMap'],\n ): Promise<void> {\n const previousChains = this.#enabledChains;\n this.#enabledChains = this.#extractEnabledChains(enabledNetworkMap);\n\n // Find newly enabled chains (in new set but not in previous)\n const addedChains: ChainId[] = [];\n for (const chain of this.#enabledChains) {\n if (!previousChains.has(chain)) {\n addedChains.push(chain);\n }\n }\n\n // Find disabled chains to clean up (in previous but not in new)\n const removedChains: ChainId[] = [];\n for (const chain of previousChains) {\n if (!this.#enabledChains.has(chain)) {\n removedChains.push(chain);\n }\n }\n\n log('Enabled networks changed', {\n previousCount: previousChains.size,\n newCount: this.#enabledChains.size,\n addedChains,\n removedChains,\n });\n\n // Note: We intentionally do NOT delete balance data for disabled chains.\n // Users may want to see historical balances even if the network is currently disabled.\n // The data will simply not be updated until the network is re-enabled.\n\n // Refresh subscriptions for new chain set\n this.#subscribeAssets();\n\n // Do one-time fetch for newly enabled chains\n if (addedChains.length > 0 && this.#selectedAccounts.length > 0) {\n await this.getAssets(this.#selectedAccounts, {\n chainIds: addedChains,\n forceUpdate: true,\n });\n }\n }\n\n /**\n * Handle assets updated from a data source.\n * Called via the onAssetsUpdate callback passed in SubscriptionRequest when the controller subscribes to a data source.\n * Enriches the response with token metadata (via middlewares) before updating state.\n *\n * @param response - The data response with updated assets\n * @param sourceId - The data source ID reporting the update\n * @param request - Optional original request for context when enriching\n */\n async handleAssetsUpdate(\n response: DataResponse,\n sourceId: string,\n request?: DataRequest,\n ): Promise<void> {\n log('Assets updated from data source', {\n sourceId,\n hasBalance: Boolean(response.assetsBalance),\n hasPrice: Boolean(response.assetsPrice),\n });\n\n // Run through enrichment middlewares (Event Stack: Detection → Token → Price)\n // Include 'metadata' in dataTypes so TokenDataSource runs to enrich detected assets\n const enrichedResponse = await this.#executeMiddlewares(\n [\n this.#detectionMiddleware.assetsMiddleware,\n this.#tokenDataSource.assetsMiddleware,\n this.#priceDataSource.assetsMiddleware,\n ],\n request ?? {\n accountsWithSupportedChains: [],\n chainIds: [],\n dataTypes: ['balance', 'metadata', 'price'],\n },\n response,\n );\n\n await this.#updateState(enrichedResponse);\n }\n\n // ============================================================================\n // CLEANUP\n // ============================================================================\n\n destroy(): void {\n log('Destroying AssetsController', {\n dataSourceCount: this.#subscriptionBalanceDataSources.length,\n subscriptionCount: this.#activeSubscriptions.size,\n });\n\n // Destroy instantiated data sources\n this.#backendWebsocketDataSource?.destroy?.();\n this.#accountsApiDataSource?.destroy?.();\n this.#snapDataSource?.destroy?.();\n if (\n this.#rpcDataSource &&\n 'destroy' in this.#rpcDataSource &&\n typeof (this.#rpcDataSource as { destroy: () => void }).destroy ===\n 'function'\n ) {\n (this.#rpcDataSource as { destroy: () => void }).destroy();\n }\n\n // Stop all active subscriptions\n this.#stop();\n\n // Unregister action handlers\n this.messenger.unregisterActionHandler('AssetsController:getAssets');\n this.messenger.unregisterActionHandler('AssetsController:getAssetsBalance');\n this.messenger.unregisterActionHandler('AssetsController:getAssetMetadata');\n this.messenger.unregisterActionHandler('AssetsController:getAssetsPrice');\n this.messenger.unregisterActionHandler('AssetsController:addCustomAsset');\n this.messenger.unregisterActionHandler(\n 'AssetsController:removeCustomAsset',\n );\n this.messenger.unregisterActionHandler('AssetsController:getCustomAssets');\n this.messenger.unregisterActionHandler('AssetsController:hideAsset');\n this.messenger.unregisterActionHandler('AssetsController:unhideAsset');\n }\n}\n"]}
1
+ {"version":3,"file":"AssetsController.cjs","sourceRoot":"","sources":["../src/AssetsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n} from '@metamask/account-tree-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n ApiPlatformClient,\n BackendWebSocketServiceActions,\n BackendWebSocketServiceEvents,\n} from '@metamask/core-backend';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkEnablementControllerGetStateAction,\n NetworkEnablementControllerEvents,\n NetworkEnablementControllerState,\n} from '@metamask/network-enablement-controller';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BigNumberJS from 'bignumber.js';\nimport { isEqual } from 'lodash';\n\nimport type { AssetsControllerMethodActions } from './AssetsController-method-action-types';\nimport type {\n AbstractDataSource,\n DataSourceState,\n SubscriptionRequest,\n} from './data-sources/AbstractDataSource';\nimport { AccountsApiDataSource } from './data-sources/AccountsApiDataSource';\nimport { BackendWebsocketDataSource } from './data-sources/BackendWebsocketDataSource';\nimport { PriceDataSource } from './data-sources/PriceDataSource';\nimport type { RpcDataSourceConfig } from './data-sources/RpcDataSource';\nimport { RpcDataSource } from './data-sources/RpcDataSource';\nimport { SnapDataSource } from './data-sources/SnapDataSource';\nimport { TokenDataSource } from './data-sources/TokenDataSource';\nimport { projectLogger, createModuleLogger } from './logger';\nimport { DetectionMiddleware } from './middlewares/DetectionMiddleware';\nimport type {\n AccountId,\n AssetPreferences,\n ChainId,\n Caip19AssetId,\n AssetMetadata,\n AssetPrice,\n AssetBalance,\n AccountWithSupportedChains,\n AssetType,\n DataType,\n DataRequest,\n DataResponse,\n NextFunction,\n Middleware,\n SubscriptionResponse,\n Asset,\n AssetsControllerStateInternal,\n} from './types';\nimport { normalizeAssetId } from './utils';\n\n// ============================================================================\n// CONTROLLER CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'AssetsController' as const;\n\n/** Method names exposed as messenger actions (AssetsController:getAssets, etc.) */\nconst MESSENGER_EXPOSED_METHODS = [\n 'getAssets',\n 'getAssetsBalance',\n 'getAssetMetadata',\n 'getAssetsPrice',\n 'addCustomAsset',\n 'removeCustomAsset',\n 'getCustomAssets',\n 'hideAsset',\n 'unhideAsset',\n] as const;\n\n/** Default polling interval hint for data sources (30 seconds) */\nconst DEFAULT_POLLING_INTERVAL_MS = 30_000;\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// STATE TYPES\n// ============================================================================\n\n/**\n * State structure for AssetsController.\n *\n * All values are JSON-serializable. UI preferences (e.g. hidden) are in\n * assetPreferences, not in metadata.\n *\n * @see AssetsControllerStateInternal for the semantic type structure\n */\nexport type AssetsControllerState = {\n /** Shared metadata for all assets (stored once per asset) */\n assetsMetadata: { [assetId: string]: AssetMetadata };\n /** Per-account balance data */\n assetsBalance: { [accountId: string]: { [assetId: string]: AssetBalance } };\n /** Price data for assets */\n assetsPrice: { [assetId: string]: AssetPrice };\n /** Custom assets added by users per account (CAIP-19 asset IDs) */\n customAssets: { [accountId: string]: Caip19AssetId[] };\n /** UI preferences per asset (e.g. hidden) */\n assetPreferences: { [assetId: string]: AssetPreferences };\n};\n\n/**\n * Returns the default state for AssetsController.\n *\n * @returns The default AssetsController state with empty maps.\n */\nexport function getDefaultAssetsControllerState(): AssetsControllerState {\n return {\n assetsMetadata: {},\n assetsBalance: {},\n assetsPrice: {},\n customAssets: {},\n assetPreferences: {},\n };\n}\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\nexport type AssetsControllerGetStateAction = ControllerGetStateAction<\n typeof CONTROLLER_NAME,\n AssetsControllerState\n>;\n\nexport type AssetsControllerActions =\n | AssetsControllerGetStateAction\n | AssetsControllerMethodActions;\n\nexport type AssetsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof CONTROLLER_NAME,\n AssetsControllerState\n>;\n\nexport type AssetsControllerBalanceChangedEvent = {\n type: `${typeof CONTROLLER_NAME}:balanceChanged`;\n payload: [\n {\n accountId: AccountId;\n assetId: Caip19AssetId;\n previousAmount: string;\n newAmount: string;\n },\n ];\n};\n\nexport type AssetsControllerPriceChangedEvent = {\n type: `${typeof CONTROLLER_NAME}:priceChanged`;\n payload: [{ prices: Record<Caip19AssetId, AssetPrice> }];\n};\n\nexport type AssetsControllerAssetsDetectedEvent = {\n type: `${typeof CONTROLLER_NAME}:assetsDetected`;\n payload: [{ accountId: AccountId; assetIds: Caip19AssetId[] }];\n};\n\nexport type AssetsControllerEvents =\n | AssetsControllerStateChangeEvent\n | AssetsControllerBalanceChangedEvent\n | AssetsControllerPriceChangedEvent\n | AssetsControllerAssetsDetectedEvent;\n\ntype AllowedActions =\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | NetworkEnablementControllerGetStateAction\n // BackendWebsocketDataSource calls BackendWebSocketService\n | BackendWebSocketServiceActions;\n\ntype AllowedEvents =\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | NetworkEnablementControllerEvents\n | BackendWebSocketServiceEvents\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent;\n\nexport type AssetsControllerMessenger = Messenger<\n typeof CONTROLLER_NAME,\n AssetsControllerActions | AllowedActions,\n AssetsControllerEvents | AllowedEvents\n>;\n\n// ============================================================================\n// CONTROLLER OPTIONS\n// ============================================================================\n\nexport type AssetsControllerOptions = {\n messenger: AssetsControllerMessenger;\n state?: Partial<AssetsControllerState>;\n /** Default polling interval hint passed to data sources (ms) */\n defaultUpdateInterval?: number;\n /** Function to determine if the controller is enabled. Defaults to true. */\n isEnabled?: () => boolean;\n /**\n * API client for balance/price/metadata. The controller instantiates data sources\n * and uses them directly when this is provided.\n */\n queryApiClient: ApiPlatformClient;\n /** Optional configuration for RpcDataSource. */\n rpcDataSourceConfig?: RpcDataSourceConfig;\n};\n\n// ============================================================================\n// STATE METADATA\n// ============================================================================\n\nconst stateMetadata: StateMetadata<AssetsControllerState> = {\n assetsMetadata: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetsBalance: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetsPrice: {\n persist: false,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n customAssets: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetPreferences: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\nfunction extractChainId(assetId: Caip19AssetId): ChainId {\n const parsed = parseCaipAssetType(assetId);\n return parsed.chainId;\n}\n\n/**\n * Normalizes all asset IDs in a DataResponse.\n * This is applied at the controller level to ensure consistent state\n * regardless of how data sources format their asset IDs.\n *\n * @param response - The DataResponse to normalize.\n * @returns The normalized DataResponse with checksummed EVM addresses.\n */\nfunction normalizeResponse(response: DataResponse): DataResponse {\n const normalized: DataResponse = {};\n\n if (response.assetsMetadata) {\n normalized.assetsMetadata = {};\n for (const [assetId, metadata] of Object.entries(response.assetsMetadata)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsMetadata[normalizedId] = metadata;\n }\n }\n\n if (response.assetsPrice) {\n normalized.assetsPrice = {};\n for (const [assetId, price] of Object.entries(response.assetsPrice)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsPrice[normalizedId] = price;\n }\n }\n\n if (response.assetsBalance) {\n normalized.assetsBalance = {};\n for (const [accountId, balances] of Object.entries(\n response.assetsBalance,\n )) {\n normalized.assetsBalance[accountId] = {};\n for (const [assetId, balance] of Object.entries(balances)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsBalance[accountId][normalizedId] = balance;\n }\n }\n }\n\n // Preserve detectedAssets with normalized asset IDs\n if (response.detectedAssets) {\n normalized.detectedAssets = {};\n for (const [accountId, assetIds] of Object.entries(\n response.detectedAssets,\n )) {\n normalized.detectedAssets[accountId] = assetIds.map((assetId) =>\n normalizeAssetId(assetId),\n );\n }\n }\n\n // Preserve errors (chain IDs don't need normalization)\n if (response.errors) {\n normalized.errors = { ...response.errors };\n }\n\n return normalized;\n}\n\n// ============================================================================\n// CONTROLLER IMPLEMENTATION\n// ============================================================================\n\n/**\n * AssetsController provides a unified interface for managing asset balances\n * across all blockchain networks (EVM and non-EVM) and all asset types.\n *\n * ## Core Responsibilities\n *\n * 1. **One-Time Fetch (Sync)**: For initial load, force refresh, or on-demand queries.\n * Uses `getAssets()`, `getAssetsBalance()`, etc. with `forceUpdate: true`.\n *\n * 2. **Async Subscriptions**: Subscribes to data sources for ongoing updates.\n * Data sources push updates via callbacks; the controller updates state.\n *\n * 3. **Dynamic Source Selection**: Routes requests to appropriate data sources\n * based on which chains they support. When active chains change, the controller\n * dynamically adjusts subscriptions.\n *\n * 4. **Keyring Lifecycle**: Listens to KeyringController unlock/lock events to\n * start/stop subscriptions when the wallet is unlocked or locked.\n *\n * ## Architecture\n *\n * - Data sources declare their supported chains (async, can change over time)\n * - Data sources are responsible for their own update mechanisms (WebSocket, polling, events)\n * - The controller does NOT manage polling - it simply receives pushed updates\n */\nexport class AssetsController extends BaseController<\n typeof CONTROLLER_NAME,\n AssetsControllerState,\n AssetsControllerMessenger\n> {\n /** Whether the controller is enabled */\n readonly #isEnabled: boolean;\n\n /** Default update interval hint passed to data sources */\n readonly #defaultUpdateInterval: number;\n\n readonly #controllerMutex = new Mutex();\n\n /**\n * Active balance subscriptions keyed by account ID.\n * Each account has one logical subscription that may span multiple data sources.\n * For example, if WebSocket covers chains A,B and RPC covers chain C,\n * the account subscribes to both data sources for its chains.\n */\n readonly #activeSubscriptions: Map<string, SubscriptionResponse> = new Map();\n\n /** Currently enabled chains from NetworkEnablementController */\n #enabledChains: Set<ChainId> = new Set();\n\n /**\n * Get the currently selected accounts from AccountTreeController.\n * This includes all accounts in the same group as the selected account\n * (EVM, Bitcoin, Solana, Tron, etc. that belong to the same logical account group).\n *\n * @returns Array of InternalAccount objects from the selected account group.\n */\n get #selectedAccounts(): InternalAccount[] {\n return this.messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n }\n\n readonly #backendWebsocketDataSource: BackendWebsocketDataSource;\n\n readonly #accountsApiDataSource: AccountsApiDataSource;\n\n readonly #snapDataSource: SnapDataSource;\n\n readonly #rpcDataSource: RpcDataSource;\n\n /**\n * Subscription balance data sources in assignment priority order (first that supports a chain gets it).\n *\n * @returns The four balance data source instances in priority order.\n */\n get #subscriptionBalanceDataSources(): [\n BackendWebsocketDataSource,\n AccountsApiDataSource,\n SnapDataSource,\n RpcDataSource,\n ] {\n return [\n this.#backendWebsocketDataSource,\n this.#accountsApiDataSource,\n this.#snapDataSource,\n this.#rpcDataSource,\n ];\n }\n\n readonly #priceDataSource: PriceDataSource;\n\n readonly #detectionMiddleware: DetectionMiddleware;\n\n readonly #tokenDataSource: TokenDataSource;\n\n constructor({\n messenger,\n state = {},\n defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS,\n isEnabled = (): boolean => true,\n queryApiClient,\n rpcDataSourceConfig,\n }: AssetsControllerOptions) {\n super({\n name: CONTROLLER_NAME,\n messenger,\n metadata: stateMetadata,\n state: {\n ...getDefaultAssetsControllerState(),\n ...state,\n },\n });\n\n this.#isEnabled = isEnabled();\n this.#defaultUpdateInterval = defaultUpdateInterval;\n const rpcConfig = rpcDataSourceConfig ?? {};\n\n const onActiveChainsUpdated = (\n dataSourceName: string,\n chains: ChainId[],\n previousChains: ChainId[],\n ): void =>\n this.handleActiveChainsUpdate(dataSourceName, chains, previousChains);\n\n this.#backendWebsocketDataSource = new BackendWebsocketDataSource({\n messenger: this.messenger,\n queryApiClient,\n onActiveChainsUpdated,\n });\n this.#accountsApiDataSource = new AccountsApiDataSource({\n queryApiClient,\n onActiveChainsUpdated,\n });\n this.#snapDataSource = new SnapDataSource({\n messenger: this.messenger,\n onActiveChainsUpdated,\n });\n this.#rpcDataSource = new RpcDataSource({\n messenger: this.messenger,\n onActiveChainsUpdated,\n ...rpcConfig,\n });\n this.#tokenDataSource = new TokenDataSource({\n queryApiClient,\n });\n this.#priceDataSource = new PriceDataSource({\n queryApiClient,\n });\n this.#detectionMiddleware = new DetectionMiddleware();\n\n if (!this.#isEnabled) {\n log('AssetsController is disabled, skipping initialization');\n return;\n }\n\n log('Initializing AssetsController', {\n defaultUpdateInterval: this.#defaultUpdateInterval,\n });\n\n this.#initializeState();\n this.#subscribeToEvents();\n this.#registerActionHandlers();\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n #initializeState(): void {\n const { enabledNetworkMap } = this.messenger.call(\n 'NetworkEnablementController:getState',\n );\n this.#enabledChains = this.#extractEnabledChains(enabledNetworkMap);\n\n log('Initialized state', {\n enabledNetworkMap,\n enabledChains: this.#enabledChains,\n });\n }\n\n /**\n * Extract enabled chains from enabledNetworkMap.\n * Returns CAIP-2 chain IDs for all enabled networks across all namespaces.\n *\n * Note: For EIP155 (EVM) chains, the reference is normalized to decimal format\n * to ensure consistency with CAIP-2 standard and API responses.\n *\n * @param enabledNetworkMap - The enabled network map from NetworkEnablementController.\n * @returns Set of CAIP-2 chain IDs for all enabled networks.\n */\n #extractEnabledChains(\n enabledNetworkMap: NetworkEnablementControllerState['enabledNetworkMap'],\n ): Set<ChainId> {\n const chains = new Set<ChainId>();\n\n for (const [namespace, networks] of Object.entries(enabledNetworkMap)) {\n for (const [reference, isEnabled] of Object.entries(networks)) {\n if (isEnabled) {\n // Check if reference is already a full CAIP-2 chain ID (contains colon)\n if (reference.includes(':')) {\n // Already a full chain ID, use as-is\n chains.add(reference as ChainId);\n } else {\n // Normalize EIP155 chain references from hex to decimal (CAIP-2 standard)\n const normalizedReference = this.#normalizeChainReference(\n namespace,\n reference,\n );\n chains.add(`${namespace}:${normalizedReference}`);\n }\n }\n }\n }\n return chains;\n }\n\n /**\n * Normalize chain reference to CAIP-2 standard format.\n * For EIP155, converts hex chain IDs to decimal.\n *\n * @param namespace - The chain namespace (e.g., \"eip155\").\n * @param reference - The chain reference (e.g., \"0x1\" or \"1\").\n * @returns The normalized chain reference in decimal format.\n */\n #normalizeChainReference(namespace: string, reference: string): string {\n if (namespace === 'eip155' && reference.startsWith('0x')) {\n // Convert hex to decimal for EIP155 chains\n return parseInt(reference, 16).toString();\n }\n return reference;\n }\n\n #subscribeToEvents(): void {\n // Subscribe to account group changes (when user switches between account groups like Account 1 -> Account 2)\n this.messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n () => {\n this.#handleAccountGroupChanged().catch(console.error);\n },\n );\n\n // Subscribe to network enablement changes (only enabledNetworkMap)\n this.messenger.subscribe(\n 'NetworkEnablementController:stateChange',\n ({ enabledNetworkMap }) => {\n this.#handleEnabledNetworksChanged(enabledNetworkMap).catch(\n console.error,\n );\n },\n );\n\n // Keyring lifecycle: start when unlocked, stop when locked\n this.messenger.subscribe('KeyringController:unlock', () => this.#start());\n this.messenger.subscribe('KeyringController:lock', () => this.#stop());\n }\n\n #registerActionHandlers(): void {\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n // ============================================================================\n // DATA SOURCE CHAIN MANAGEMENT\n // ============================================================================\n\n /**\n * Handle when a data source's supported chains change.\n * Used to refresh balance subscriptions and run a one-time fetch when a new chain is supported.\n *\n * - On any add/remove: re-subscribes to data sources so chain assignment stays correct.\n * - When chains are added: fetches balances for the new chains (for selected accounts on enabled networks).\n *\n * Controller does not store chains; sources report via this callback. previousChains is required for diff.\n *\n * @param dataSourceId - The identifier of the data source reporting the change.\n * @param activeChains - Currently active (supported and available) chain IDs for this source.\n * @param previousChains - Previous chains; used to compute added/removed.\n */\n handleActiveChainsUpdate(\n dataSourceId: string,\n activeChains: ChainId[],\n previousChains: ChainId[],\n ): void {\n log('Data source active chains changed', {\n dataSourceId,\n chainCount: activeChains.length,\n chains: activeChains,\n });\n\n const previous: ChainId[] = previousChains;\n\n const previousSet = new Set(previous);\n const addedChains = activeChains.filter((ch) => !previousSet.has(ch));\n const removedChains = previous.filter((ch) => !activeChains.includes(ch));\n\n if (addedChains.length > 0 || removedChains.length > 0) {\n // Refresh subscriptions to use updated data source availability\n this.#subscribeAssets();\n }\n\n // If chains were added and we have selected accounts, do one-time fetch\n if (addedChains.length > 0 && this.#selectedAccounts.length > 0) {\n const addedEnabledChains = addedChains.filter((chain) =>\n this.#enabledChains.has(chain),\n );\n if (addedEnabledChains.length > 0) {\n log('Fetching balances for newly added chains', { addedEnabledChains });\n this.getAssets(this.#selectedAccounts, {\n chainIds: addedEnabledChains,\n forceUpdate: true,\n }).catch((error) => {\n log('Failed to fetch balance for added chains', { error });\n });\n }\n }\n }\n\n // ============================================================================\n // MIDDLEWARE EXECUTION\n // ============================================================================\n\n /**\n * Execute middlewares with request/response context.\n *\n * @param middlewares - Middlewares to execute in order.\n * @param request - The data request.\n * @param initialResponse - Optional initial response (for enriching existing data).\n * @returns The final DataResponse after all middlewares have processed.\n */\n async #executeMiddlewares(\n middlewares: Middleware[],\n request: DataRequest,\n initialResponse: DataResponse = {},\n ): Promise<DataResponse> {\n const chain = middlewares.reduceRight<NextFunction>(\n (next, middleware) =>\n async (\n ctx,\n ): Promise<{\n request: DataRequest;\n response: DataResponse;\n getAssetsState: () => AssetsControllerStateInternal;\n }> => {\n try {\n return await middleware(ctx, next);\n } catch (error) {\n console.error('[AssetsController] Middleware failed:', error);\n return next(ctx);\n }\n },\n async (ctx) => ctx,\n );\n\n const result = await chain({\n request,\n response: initialResponse,\n getAssetsState: () => this.state as AssetsControllerStateInternal,\n });\n return result.response;\n }\n\n // ============================================================================\n // PUBLIC API: QUERY METHODS\n // ============================================================================\n\n async getAssets(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n dataTypes?: DataType[];\n },\n ): Promise<Record<AccountId, Record<Caip19AssetId, Asset>>> {\n const chainIds = options?.chainIds ?? [...this.#enabledChains];\n const assetTypes = options?.assetTypes ?? ['fungible'];\n const dataTypes = options?.dataTypes ?? ['balance', 'metadata', 'price'];\n\n // Collect custom assets for all requested accounts\n const customAssets: Caip19AssetId[] = [];\n for (const account of accounts) {\n const accountCustomAssets = this.getCustomAssets(account.id);\n customAssets.push(...accountCustomAssets);\n }\n\n if (options?.forceUpdate) {\n const request = this.#buildDataRequest(accounts, chainIds, {\n assetTypes,\n dataTypes,\n customAssets: customAssets.length > 0 ? customAssets : undefined,\n forceUpdate: true,\n });\n const response = await this.#executeMiddlewares(\n [\n this.#accountsApiDataSource.assetsMiddleware,\n this.#snapDataSource.assetsMiddleware,\n this.#rpcDataSource.assetsMiddleware,\n this.#detectionMiddleware.assetsMiddleware,\n this.#tokenDataSource.assetsMiddleware,\n this.#priceDataSource.assetsMiddleware,\n ],\n request,\n );\n await this.#updateState(response);\n }\n\n return this.#getAssetsFromState(accounts, chainIds, assetTypes);\n }\n\n async getAssetsBalance(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n },\n ): Promise<Record<AccountId, Record<Caip19AssetId, AssetBalance>>> {\n // Reuse getAssets with dataTypes: ['balance'] only\n const assets = await this.getAssets(accounts, {\n chainIds: options?.chainIds,\n assetTypes: options?.assetTypes,\n forceUpdate: options?.forceUpdate,\n dataTypes: ['balance', 'metadata'],\n });\n\n // Extract just the balance from each asset\n const result: Record<AccountId, Record<Caip19AssetId, AssetBalance>> = {};\n for (const [accountId, accountAssets] of Object.entries(assets)) {\n result[accountId] = {};\n for (const [assetId, asset] of Object.entries(accountAssets)) {\n if (asset.balance) {\n result[accountId][assetId as Caip19AssetId] = asset.balance;\n }\n }\n }\n\n return result;\n }\n\n getAssetMetadata(assetId: Caip19AssetId): AssetMetadata | undefined {\n return this.state.assetsMetadata[assetId] as AssetMetadata | undefined;\n }\n\n async getAssetsPrice(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n },\n ): Promise<Record<Caip19AssetId, AssetPrice>> {\n const assets = await this.getAssets(accounts, {\n chainIds: options?.chainIds,\n assetTypes: options?.assetTypes,\n forceUpdate: options?.forceUpdate,\n dataTypes: ['price'],\n });\n\n // Extract just the price from each asset (flattened across accounts)\n const result: Record<Caip19AssetId, AssetPrice> = {};\n for (const accountAssets of Object.values(assets)) {\n for (const [assetId, asset] of Object.entries(accountAssets)) {\n if (asset.price) {\n result[assetId as Caip19AssetId] = asset.price;\n }\n }\n }\n\n return result;\n }\n\n // ============================================================================\n // CUSTOM ASSETS MANAGEMENT\n // ============================================================================\n\n /**\n * Add a custom asset for an account.\n * Custom assets are included in subscription and fetch operations.\n * Adding a custom asset also unhides it if it was previously hidden.\n *\n * @param accountId - The account ID to add the custom asset for.\n * @param assetId - The CAIP-19 asset ID to add.\n */\n async addCustomAsset(\n accountId: AccountId,\n assetId: Caip19AssetId,\n ): Promise<void> {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Adding custom asset', { accountId, assetId: normalizedAssetId });\n\n this.update((state) => {\n const customAssets = state.customAssets as Record<string, string[]>;\n if (!customAssets[accountId]) {\n customAssets[accountId] = [];\n }\n\n // Only add if not already present\n if (!customAssets[accountId].includes(normalizedAssetId)) {\n customAssets[accountId].push(normalizedAssetId);\n }\n\n // Unhide the asset if it was hidden (via assetPreferences)\n const prefs = state.assetPreferences[normalizedAssetId];\n if (prefs?.hidden) {\n delete prefs.hidden;\n if (Object.keys(prefs).length === 0) {\n delete state.assetPreferences[normalizedAssetId];\n }\n }\n });\n\n // Fetch data for the newly added custom asset\n const account = this.#selectedAccounts.find((a) => a.id === accountId);\n if (account) {\n const chainId = extractChainId(normalizedAssetId);\n await this.getAssets([account], {\n chainIds: [chainId],\n forceUpdate: true,\n });\n }\n }\n\n /**\n * Remove a custom asset from an account.\n *\n * @param accountId - The account ID to remove the custom asset from.\n * @param assetId - The CAIP-19 asset ID to remove.\n */\n removeCustomAsset(accountId: AccountId, assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Removing custom asset', { accountId, assetId: normalizedAssetId });\n\n this.update((state) => {\n if (state.customAssets[accountId]) {\n state.customAssets[accountId] = state.customAssets[accountId].filter(\n (id) => id !== normalizedAssetId,\n );\n\n // Clean up empty arrays\n if (state.customAssets[accountId].length === 0) {\n delete state.customAssets[accountId];\n }\n }\n });\n }\n\n /**\n * Get all custom assets for an account.\n *\n * @param accountId - The account ID to get custom assets for.\n * @returns Array of CAIP-19 asset IDs for the account's custom assets.\n */\n getCustomAssets(accountId: AccountId): Caip19AssetId[] {\n return this.state.customAssets[accountId] ?? [];\n }\n\n // ============================================================================\n // HIDDEN ASSETS MANAGEMENT\n // ============================================================================\n\n /**\n * Hide an asset globally.\n * Hidden assets are excluded from the asset list returned by getAssets.\n * The hidden state is stored in assetPreferences.\n *\n * @param assetId - The CAIP-19 asset ID to hide.\n */\n hideAsset(assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Hiding asset', { assetId: normalizedAssetId });\n\n this.update((state) => {\n if (!state.assetPreferences[normalizedAssetId]) {\n state.assetPreferences[normalizedAssetId] = {};\n }\n state.assetPreferences[normalizedAssetId].hidden = true;\n });\n }\n\n /**\n * Unhide an asset globally.\n *\n * @param assetId - The CAIP-19 asset ID to unhide.\n */\n unhideAsset(assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Unhiding asset', { assetId: normalizedAssetId });\n\n this.update((state) => {\n const prefs = state.assetPreferences[normalizedAssetId];\n if (prefs) {\n delete prefs.hidden;\n if (Object.keys(prefs).length === 0) {\n delete state.assetPreferences[normalizedAssetId];\n }\n }\n });\n }\n\n // ============================================================================\n // SUBSCRIPTIONS\n // ============================================================================\n\n /**\n * Subscribe to price updates for all assets held by the given accounts.\n * Polls PriceDataSource which fetches prices from balance state.\n *\n * @param accounts - Accounts to subscribe price updates for.\n * @param chainIds - Chain IDs to filter prices for.\n * @param options - Subscription options.\n * @param options.updateInterval - Polling interval in ms.\n */\n subscribeAssetsPrice(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n options: { updateInterval?: number } = {},\n ): void {\n const { updateInterval = this.#defaultUpdateInterval } = options;\n const subscriptionKey = 'ds:PriceDataSource';\n\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n const isUpdate = existingSubscription !== undefined;\n\n const subscribeReq: SubscriptionRequest = {\n request: this.#buildDataRequest(accounts, chainIds, {\n dataTypes: ['price'],\n updateInterval,\n }),\n subscriptionId: subscriptionKey,\n isUpdate,\n onAssetsUpdate: (response) =>\n this.handleAssetsUpdate(response, 'PriceDataSource'),\n getAssetsState: () => this.state,\n };\n\n this.#priceDataSource.subscribe(subscribeReq).catch(console.error);\n\n // Track subscription\n const subscription: SubscriptionResponse = {\n chains: chainIds,\n accountId: subscriptionKey,\n assetTypes: ['fungible'],\n dataTypes: ['price'],\n unsubscribe: () => {\n this.#activeSubscriptions.delete(subscriptionKey);\n },\n };\n\n this.#activeSubscriptions.set(subscriptionKey, subscription);\n }\n\n /**\n * Unsubscribe from price updates.\n */\n unsubscribeAssetsPrice(): void {\n const subscriptionKey = 'ds:PriceDataSource';\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n\n if (!existingSubscription) {\n return;\n }\n this.#priceDataSource.unsubscribe(subscriptionKey).catch(console.error);\n existingSubscription.unsubscribe();\n }\n\n // ============================================================================\n // STATE MANAGEMENT\n // ============================================================================\n\n async #updateState(response: DataResponse): Promise<void> {\n // Normalize asset IDs (checksum EVM addresses) before storing in state\n const normalizedResponse = normalizeResponse(response);\n\n const releaseLock = await this.#controllerMutex.acquire();\n\n try {\n const previousState = this.state;\n const previousPrices = { ...this.state.assetsPrice };\n // Use detectedAssets from response (assets without metadata)\n const detectedAssets: Record<AccountId, Caip19AssetId[]> =\n normalizedResponse.detectedAssets ?? {};\n\n // Track actual changes for logging\n const changedBalances: {\n accountId: string;\n assetId: string;\n oldAmount: string | undefined;\n newAmount: string;\n }[] = [];\n const changedMetadata: string[] = [];\n\n this.update((state) => {\n // Use type assertions to avoid deep type instantiation issues with Immer Draft types\n const metadata = state.assetsMetadata as Record<string, AssetMetadata>;\n const balances = state.assetsBalance as Record<\n string,\n Record<string, AssetBalance>\n >;\n const prices = state.assetsPrice as Record<string, AssetPrice>;\n\n if (normalizedResponse.assetsMetadata) {\n for (const [key, value] of Object.entries(\n normalizedResponse.assetsMetadata,\n )) {\n if (\n !isEqual(\n previousState.assetsMetadata[key as Caip19AssetId],\n value,\n )\n ) {\n changedMetadata.push(key);\n }\n metadata[key] = value;\n }\n }\n\n if (normalizedResponse.assetsBalance) {\n for (const [accountId, accountBalances] of Object.entries(\n normalizedResponse.assetsBalance,\n )) {\n const previousBalances =\n previousState.assetsBalance[accountId] ?? {};\n\n if (!balances[accountId]) {\n balances[accountId] = {};\n }\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n const previousBalance = previousBalances[\n assetId as Caip19AssetId\n ] as { amount: string } | undefined;\n const balanceData = balance as { amount: string };\n const newAmount = balanceData.amount;\n const oldAmount = previousBalance?.amount;\n\n // Track if balance actually changed\n if (oldAmount !== newAmount) {\n changedBalances.push({\n accountId,\n assetId,\n oldAmount,\n newAmount,\n });\n }\n }\n\n Object.assign(balances[accountId], accountBalances);\n }\n }\n\n // Update prices in state\n if (normalizedResponse.assetsPrice) {\n for (const [key, value] of Object.entries(\n normalizedResponse.assetsPrice,\n )) {\n prices[key] = value;\n }\n }\n });\n\n // Calculate changed prices\n const changedPriceAssets: string[] = normalizedResponse.assetsPrice\n ? Object.keys(normalizedResponse.assetsPrice).filter(\n (assetId) =>\n !isEqual(\n previousPrices[assetId as Caip19AssetId],\n normalizedResponse.assetsPrice?.[assetId as Caip19AssetId],\n ),\n )\n : [];\n\n // Log only actual changes\n if (\n changedBalances.length > 0 ||\n changedMetadata.length > 0 ||\n changedPriceAssets.length > 0\n ) {\n log('State updated', {\n changedBalances:\n changedBalances.length > 0 ? changedBalances : undefined,\n changedMetadataCount:\n changedMetadata.length > 0 ? changedMetadata.length : undefined,\n changedPricesCount:\n changedPriceAssets.length > 0\n ? changedPriceAssets.length\n : undefined,\n newAssets:\n Object.keys(detectedAssets).length > 0\n ? Object.entries(detectedAssets).map(([accountId, assets]) => ({\n accountId,\n assets,\n }))\n : undefined,\n });\n }\n\n // Publish balance changed events\n for (const change of changedBalances) {\n this.messenger.publish('AssetsController:balanceChanged', {\n accountId: change.accountId,\n assetId: change.assetId as Caip19AssetId,\n previousAmount: change.oldAmount ?? '0',\n newAmount: change.newAmount,\n });\n }\n\n // Publish price changed event with full price data\n if (changedPriceAssets.length > 0 && normalizedResponse.assetsPrice) {\n // Build prices object with only changed prices\n const changedPrices: Record<Caip19AssetId, AssetPrice> = {};\n for (const assetId of changedPriceAssets) {\n const price =\n normalizedResponse.assetsPrice[assetId as Caip19AssetId];\n if (price) {\n changedPrices[assetId as Caip19AssetId] = price;\n }\n }\n this.messenger.publish('AssetsController:priceChanged', {\n prices: changedPrices,\n });\n }\n\n // Publish assets detected events\n for (const [accountId, assetIds] of Object.entries(detectedAssets)) {\n if (assetIds.length > 0) {\n this.messenger.publish('AssetsController:assetsDetected', {\n accountId,\n assetIds,\n });\n }\n }\n } finally {\n releaseLock();\n }\n }\n\n #getAssetsFromState(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n assetTypes: AssetType[],\n ): Record<AccountId, Record<Caip19AssetId, Asset>> {\n const result: Record<AccountId, Record<Caip19AssetId, Asset>> = {};\n // Convert to Sets for O(1) lookups\n const chainIdSet = new Set(chainIds);\n const assetTypeSet = new Set(assetTypes);\n\n for (const account of accounts) {\n result[account.id] = {};\n\n const accountBalances = this.state.assetsBalance[account.id] ?? {};\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n const typedAssetId = assetId as Caip19AssetId;\n\n const metadataRaw = this.state.assetsMetadata[typedAssetId];\n\n // Skip assets without metadata\n if (!metadataRaw) {\n continue;\n }\n\n const metadata = metadataRaw;\n\n // Skip hidden assets (assetPreferences)\n const prefs = this.state.assetPreferences[typedAssetId];\n if (prefs?.hidden) {\n continue;\n }\n\n const assetChainId = extractChainId(typedAssetId);\n\n if (!chainIdSet.has(assetChainId)) {\n continue;\n }\n\n // Filter by asset type\n const tokenAssetType = this.#tokenStandardToAssetType(metadata.type);\n if (!assetTypeSet.has(tokenAssetType)) {\n continue;\n }\n\n const typedBalance = balance;\n const priceRaw = this.state.assetsPrice[typedAssetId];\n const price: AssetPrice = priceRaw ?? {\n price: 0,\n lastUpdated: 0,\n };\n\n // Compute fiat value using BigNumber for precision\n // Note: typedBalance.amount is already in human-readable format (e.g., \"1\" for 1 ETH)\n // so we do NOT divide by 10^decimals here\n const balanceAmount = new BigNumberJS(typedBalance.amount || '0');\n const fiatValue = balanceAmount\n .multipliedBy(price.price || 0)\n .toNumber();\n\n const asset: Asset = {\n id: typedAssetId,\n chainId: assetChainId,\n balance: typedBalance,\n metadata,\n price,\n fiatValue,\n };\n\n result[account.id][typedAssetId] = asset;\n }\n }\n\n return result;\n }\n\n /**\n * Maps a token standard to its corresponding asset type.\n *\n * @param tokenStandard - The token standard from metadata.\n * @returns The corresponding asset type.\n */\n #tokenStandardToAssetType(tokenStandard: string): AssetType {\n switch (tokenStandard) {\n case 'native':\n case 'erc20':\n case 'spl':\n return 'fungible';\n case 'erc721':\n return 'nft';\n case 'erc1155':\n // ERC1155 can be either fungible or non-fungible, treat as collectible\n return 'collectible';\n default:\n // Unknown standards default to fungible\n return 'fungible';\n }\n }\n\n // ============================================================================\n // START / STOP\n // ============================================================================\n\n /**\n * Start asset tracking: subscribe to updates and fetch current balances.\n * Called when app opens, account changes, or keyring unlocks.\n */\n #start(): void {\n log('Starting asset tracking', {\n selectedAccountCount: this.#selectedAccounts.length,\n enabledChainCount: this.#enabledChains.size,\n });\n\n this.#subscribeAssets();\n if (this.#selectedAccounts.length > 0) {\n this.getAssets(this.#selectedAccounts, {\n chainIds: [...this.#enabledChains],\n forceUpdate: true,\n }).catch((error) => {\n log('Failed to fetch assets', error);\n });\n }\n }\n\n /**\n * Stop asset tracking: unsubscribe from all updates.\n * Called when app closes or keyring locks.\n */\n #stop(): void {\n log('Stopping asset tracking', {\n activeSubscriptionCount: this.#activeSubscriptions.size,\n hasPriceSubscription: this.#activeSubscriptions.has('ds:PriceDataSource'),\n });\n\n // Stop price subscription first (uses direct messenger call)\n this.unsubscribeAssetsPrice();\n\n // Stop balance subscriptions by properly notifying data sources via messenger\n // This ensures data sources stop their polling timers\n // Convert to array first to avoid modifying map during iteration\n const subscriptionKeys = [...this.#activeSubscriptions.keys()];\n for (const subscriptionKey of subscriptionKeys) {\n if (subscriptionKey.startsWith('ds:')) {\n const sourceId = subscriptionKey.slice(3);\n const source = this.#subscriptionBalanceDataSources.find(\n (ds) => ds.getName() === sourceId,\n );\n if (source) {\n this.#unsubscribeDataSource(source);\n }\n }\n }\n this.#activeSubscriptions.clear();\n }\n\n /**\n * Subscribe to asset updates for all selected accounts.\n */\n #subscribeAssets(): void {\n if (this.#selectedAccounts.length === 0) {\n return;\n }\n\n // Subscribe to balance updates (batched by data source)\n this.#subscribeAssetsBalance(this.#selectedAccounts, [\n ...this.#enabledChains,\n ]);\n\n // Subscribe to price updates for all assets held by selected accounts\n this.subscribeAssetsPrice(this.#selectedAccounts, [...this.#enabledChains]);\n }\n\n /**\n * Subscribe to balance updates for the given accounts and chains.\n *\n * Strategy to minimize data source calls:\n * 1. Collect all chains to subscribe based on enabled networks\n * 2. Map chains to accounts based on their scopes\n * 3. Split by data source (ordered by priority) - each data source gets ONE subscription\n *\n * This ensures we make minimal subscriptions to each data source while covering\n * all accounts and chains.\n *\n * @param accounts - Accounts to subscribe balance updates for.\n * @param chainIds - Chain IDs to subscribe for.\n */\n #subscribeAssetsBalance(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n ): void {\n const chainToAccounts = this.#buildChainToAccountsMap(\n accounts,\n new Set(chainIds),\n );\n const remainingChains = new Set(chainToAccounts.keys());\n\n for (const source of this.#subscriptionBalanceDataSources) {\n const availableChains = new Set(source.getActiveChainsSync());\n const assignedChains: ChainId[] = [];\n\n for (const chainId of remainingChains) {\n if (availableChains.has(chainId)) {\n assignedChains.push(chainId);\n remainingChains.delete(chainId);\n }\n }\n\n if (assignedChains.length === 0) {\n this.#unsubscribeDataSource(source);\n continue;\n }\n\n const seenIds = new Set<string>();\n const accountsForSource = assignedChains\n .flatMap((chainId) => chainToAccounts.get(chainId) ?? [])\n .filter(\n (account) =>\n !seenIds.has(account.id) && (seenIds.add(account.id), true),\n );\n if (accountsForSource.length > 0) {\n this.#subscribeDataSource(source, accountsForSource, assignedChains);\n }\n }\n }\n\n /**\n * Build a mapping of chainId -> accounts that support that chain.\n * Only includes chains that are in the chainsToSubscribe set.\n *\n * @param accounts - Array of accounts to build mapping for.\n * @param chainsToSubscribe - Set of chain IDs to include in the mapping.\n * @returns Map of chainId to array of accounts that support that chain.\n */\n #buildChainToAccountsMap(\n accounts: InternalAccount[],\n chainsToSubscribe: Set<ChainId>,\n ): Map<ChainId, InternalAccount[]> {\n const chainToAccounts = new Map<ChainId, InternalAccount[]>();\n for (const account of accounts) {\n for (const chainId of this.#getEnabledChainsForAccount(account)) {\n if (!chainsToSubscribe.has(chainId)) {\n continue;\n }\n let list = chainToAccounts.get(chainId);\n if (!list) {\n list = [];\n chainToAccounts.set(chainId, list);\n }\n list.push(account);\n }\n }\n return chainToAccounts;\n }\n\n /**\n * Subscribe to a specific data source with accounts and chains.\n * Uses the data source name as the subscription key for batching.\n *\n * @param source - The balance data source instance.\n * @param accounts - Array of accounts to subscribe for.\n * @param chains - Array of chain IDs to subscribe for.\n */\n #subscribeDataSource(\n source: AbstractDataSource<string, DataSourceState>,\n accounts: InternalAccount[],\n chains: ChainId[],\n ): void {\n const sourceId = source.getName();\n const subscriptionKey = `ds:${sourceId}`;\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n const isUpdate = existingSubscription !== undefined;\n\n log('Subscribe to data source', {\n sourceId,\n subscriptionKey,\n isUpdate,\n accountCount: accounts.length,\n chainCount: chains.length,\n });\n\n const subscribeReq: SubscriptionRequest = {\n request: this.#buildDataRequest(accounts, chains, {\n assetTypes: ['fungible'],\n dataTypes: ['balance'],\n updateInterval: this.#defaultUpdateInterval,\n }),\n subscriptionId: subscriptionKey,\n isUpdate,\n onAssetsUpdate: (response) => this.handleAssetsUpdate(response, sourceId),\n getAssetsState: () => this.state,\n };\n\n source.subscribe(subscribeReq).catch((error) => {\n console.error(\n `[AssetsController] Failed to subscribe to '${sourceId}':`,\n error,\n );\n });\n\n // Track subscription\n const subscription: SubscriptionResponse = {\n chains,\n accountId: subscriptionKey,\n assetTypes: ['fungible'],\n dataTypes: ['balance'],\n unsubscribe: () => {\n this.#activeSubscriptions.delete(subscriptionKey);\n },\n };\n\n this.#activeSubscriptions.set(subscriptionKey, subscription);\n }\n\n /**\n * Unsubscribe from a data source if we have an active subscription.\n *\n * @param source - The balance data source instance to unsubscribe from.\n */\n #unsubscribeDataSource(\n source: AbstractDataSource<string, DataSourceState>,\n ): void {\n const subscriptionKey = `ds:${source.getName()}`;\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n\n if (existingSubscription) {\n source.unsubscribe(subscriptionKey).catch(() => undefined);\n existingSubscription.unsubscribe();\n }\n }\n\n // ============================================================================\n // HELPERS\n // ============================================================================\n\n /**\n * Build a DataRequest with accountsWithSupportedChains (enabled chains ∩ account scope ∩ requested chainIds).\n *\n * @param accounts - Accounts to include.\n * @param chainIds - Requested chain IDs (e.g. enabled chains or subset).\n * @param partial - Rest of the request (dataTypes, assetTypes, etc.).\n * @returns DataRequest with accountsWithSupportedChains and chainIds.\n */\n #buildDataRequest(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n partial: Partial<\n Omit<DataRequest, 'accountsWithSupportedChains' | 'chainIds'>\n > = {},\n ): DataRequest {\n const chainIdSet = new Set(chainIds);\n const accountsWithSupportedChains: AccountWithSupportedChains[] =\n accounts.map((account) => ({\n account,\n supportedChains: this.#getEnabledChainsForAccount(account).filter(\n (chain) => chainIdSet.has(chain),\n ),\n }));\n return {\n accountsWithSupportedChains,\n chainIds,\n ...partial,\n } as DataRequest;\n }\n\n /**\n * Get the chains that an account supports based on its scopes.\n * Returns the intersection of the account's scopes and the enabled chains.\n *\n * @param account - The account to get supported chains for.\n * @returns Array of ChainIds that the account supports and are enabled.\n */\n #getEnabledChainsForAccount(account: InternalAccount): ChainId[] {\n // Account scopes are CAIP-2 chain IDs like \"eip155:1\", \"solana:mainnet\", \"bip122:...\"\n const scopes = account.scopes ?? [];\n const result: ChainId[] = [];\n\n for (const scope of scopes) {\n const [namespace, reference] = (scope as string).split(':');\n\n // Wildcard scope (e.g., \"eip155:0\" means all enabled chains in that namespace)\n if (reference === '0') {\n for (const chain of this.#enabledChains) {\n if (chain.startsWith(`${namespace}:`)) {\n result.push(chain);\n }\n }\n } else if (namespace === 'eip155' && reference?.startsWith('0x')) {\n // Normalize hex to decimal for EIP155\n result.push(`eip155:${parseInt(reference, 16)}` as ChainId);\n } else {\n result.push(scope);\n }\n }\n\n return result;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n async #handleAccountGroupChanged(): Promise<void> {\n const accounts = this.#selectedAccounts;\n\n log('Account group changed', {\n accountCount: accounts.length,\n accountIds: accounts.map((a) => a.id),\n });\n\n // Subscribe and fetch for the new account group\n this.#subscribeAssets();\n if (accounts.length > 0) {\n await this.getAssets(accounts, {\n chainIds: [...this.#enabledChains],\n forceUpdate: true,\n });\n }\n }\n\n async #handleEnabledNetworksChanged(\n enabledNetworkMap: NetworkEnablementControllerState['enabledNetworkMap'],\n ): Promise<void> {\n const previousChains = this.#enabledChains;\n this.#enabledChains = this.#extractEnabledChains(enabledNetworkMap);\n\n // Find newly enabled chains (in new set but not in previous)\n const addedChains: ChainId[] = [];\n for (const chain of this.#enabledChains) {\n if (!previousChains.has(chain)) {\n addedChains.push(chain);\n }\n }\n\n // Find disabled chains to clean up (in previous but not in new)\n const removedChains: ChainId[] = [];\n for (const chain of previousChains) {\n if (!this.#enabledChains.has(chain)) {\n removedChains.push(chain);\n }\n }\n\n log('Enabled networks changed', {\n previousCount: previousChains.size,\n newCount: this.#enabledChains.size,\n addedChains,\n removedChains,\n });\n\n // Note: We intentionally do NOT delete balance data for disabled chains.\n // Users may want to see historical balances even if the network is currently disabled.\n // The data will simply not be updated until the network is re-enabled.\n\n // Refresh subscriptions for new chain set\n this.#subscribeAssets();\n\n // Do one-time fetch for newly enabled chains\n if (addedChains.length > 0 && this.#selectedAccounts.length > 0) {\n await this.getAssets(this.#selectedAccounts, {\n chainIds: addedChains,\n forceUpdate: true,\n });\n }\n }\n\n /**\n * Handle assets updated from a data source.\n * Called via the onAssetsUpdate callback passed in SubscriptionRequest when the controller subscribes to a data source.\n * Enriches the response with token metadata (via middlewares) before updating state.\n *\n * @param response - The data response with updated assets\n * @param sourceId - The data source ID reporting the update\n * @param request - Optional original request for context when enriching\n */\n async handleAssetsUpdate(\n response: DataResponse,\n sourceId: string,\n request?: DataRequest,\n ): Promise<void> {\n log('Assets updated from data source', {\n sourceId,\n hasBalance: Boolean(response.assetsBalance),\n hasPrice: Boolean(response.assetsPrice),\n });\n\n // Run through enrichment middlewares (Event Stack: Detection → Token → Price)\n // Include 'metadata' in dataTypes so TokenDataSource runs to enrich detected assets\n const enrichedResponse = await this.#executeMiddlewares(\n [\n this.#detectionMiddleware.assetsMiddleware,\n this.#tokenDataSource.assetsMiddleware,\n this.#priceDataSource.assetsMiddleware,\n ],\n request ?? {\n accountsWithSupportedChains: [],\n chainIds: [],\n dataTypes: ['balance', 'metadata', 'price'],\n },\n response,\n );\n\n await this.#updateState(enrichedResponse);\n }\n\n // ============================================================================\n // CLEANUP\n // ============================================================================\n\n destroy(): void {\n log('Destroying AssetsController', {\n dataSourceCount: this.#subscriptionBalanceDataSources.length,\n subscriptionCount: this.#activeSubscriptions.size,\n });\n\n // Destroy instantiated data sources\n this.#backendWebsocketDataSource?.destroy?.();\n this.#accountsApiDataSource?.destroy?.();\n this.#snapDataSource?.destroy?.();\n if (\n this.#rpcDataSource &&\n 'destroy' in this.#rpcDataSource &&\n typeof (this.#rpcDataSource as { destroy: () => void }).destroy ===\n 'function'\n ) {\n (this.#rpcDataSource as { destroy: () => void }).destroy();\n }\n\n // Stop all active subscriptions\n this.#stop();\n\n // Unregister action handlers\n this.messenger.unregisterActionHandler('AssetsController:getAssets');\n this.messenger.unregisterActionHandler('AssetsController:getAssetsBalance');\n this.messenger.unregisterActionHandler('AssetsController:getAssetMetadata');\n this.messenger.unregisterActionHandler('AssetsController:getAssetsPrice');\n this.messenger.unregisterActionHandler('AssetsController:addCustomAsset');\n this.messenger.unregisterActionHandler(\n 'AssetsController:removeCustomAsset',\n );\n this.messenger.unregisterActionHandler('AssetsController:getCustomAssets');\n this.messenger.unregisterActionHandler('AssetsController:hideAsset');\n this.messenger.unregisterActionHandler('AssetsController:unhideAsset');\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsController.d.cts","sourceRoot":"","sources":["../src/AssetsController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AssetsController.d.cts","sourceRoot":"","sources":["../src/AssetsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8DAA8D,EAC9D,oDAAoD,EACrD,0CAA0C;AAC3C,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,KAAK,EACV,iBAAiB,EACjB,8BAA8B,EAC9B,6BAA6B,EAC9B,+BAA+B;AAChC,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,qCAAqC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EACV,yCAAyC,EACzC,iCAAiC,EAElC,gDAAgD;AAMjD,OAAO,KAAK,EAAE,6BAA6B,EAAE,mDAA+C;AAS5F,OAAO,KAAK,EAAE,mBAAmB,EAAE,yCAAqC;AAMxE,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,OAAO,EACP,aAAa,EACb,aAAa,EACb,UAAU,EACV,YAAY,EAEZ,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,EAIZ,KAAK,EAEN,oBAAgB;AAOjB,QAAA,MAAM,eAAe,oBAA8B,CAAC;AAwBpD;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,6DAA6D;IAC7D,cAAc,EAAE;QAAE,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAC;IACrD,+BAA+B;IAC/B,aAAa,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG;YAAE,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAAA;SAAE,CAAA;KAAE,CAAC;IAC5E,4BAA4B;IAC5B,WAAW,EAAE;QAAE,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAC;IAC/C,mEAAmE;IACnE,YAAY,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE,CAAA;KAAE,CAAC;IACvD,6CAA6C;IAC7C,gBAAgB,EAAE;QAAE,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAAA;KAAE,CAAC;CAC3D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,qBAAqB,CAQvE;AAMD,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CACnE,OAAO,eAAe,EACtB,qBAAqB,CACtB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAC/B,8BAA8B,GAC9B,6BAA6B,CAAC;AAElC,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,CACvE,OAAO,eAAe,EACtB,qBAAqB,CACtB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,GAAG,OAAO,eAAe,iBAAiB,CAAC;IACjD,OAAO,EAAE;QACP;YACE,SAAS,EAAE,SAAS,CAAC;YACrB,OAAO,EAAE,aAAa,CAAC;YACvB,cAAc,EAAE,MAAM,CAAC;YACvB,SAAS,EAAE,MAAM,CAAC;SACnB;KACF,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,GAAG,OAAO,eAAe,eAAe,CAAC;IAC/C,OAAO,EAAE,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,UAAU,CAAC,CAAA;KAAE,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,GAAG,OAAO,eAAe,iBAAiB,CAAC;IACjD,OAAO,EAAE,CAAC;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC,CAAC;CAChE,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAC9B,gCAAgC,GAChC,mCAAmC,GACnC,iCAAiC,GACjC,mCAAmC,CAAC;AAExC,KAAK,cAAc,GACf,8DAA8D,GAC9D,yCAAyC,GAEzC,8BAA8B,CAAC;AAEnC,KAAK,aAAa,GACd,oDAAoD,GACpD,iCAAiC,GACjC,6BAA6B,GAC7B,0BAA0B,GAC1B,4BAA4B,CAAC;AAEjC,MAAM,MAAM,yBAAyB,GAAG,SAAS,CAC/C,OAAO,eAAe,EACtB,uBAAuB,GAAG,cAAc,EACxC,sBAAsB,GAAG,aAAa,CACvC,CAAC;AAMF,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,yBAAyB,CAAC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACvC,gEAAgE;IAChE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B;;;OAGG;IACH,cAAc,EAAE,iBAAiB,CAAC;IAClC,gDAAgD;IAChD,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C,CAAC;AAgHF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,gBAAiB,SAAQ,cAAc,CAClD,OAAO,eAAe,EACtB,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAkEa,EACV,SAAS,EACT,KAAU,EACV,qBAAmD,EACnD,SAA+B,EAC/B,cAAc,EACd,mBAAmB,GACpB,EAAE,uBAAuB;IAqK1B;;;;;;;;;;;;OAYG;IACH,wBAAwB,CACtB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,OAAO,EAAE,EACvB,cAAc,EAAE,OAAO,EAAE,GACxB,IAAI;IAmFD,SAAS,CACb,QAAQ,EAAE,eAAe,EAAE,EAC3B,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;QACrB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;QACzB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;KACxB,GACA,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;IAoCrD,gBAAgB,CACpB,QAAQ,EAAE,eAAe,EAAE,EAC3B,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;QACrB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;QACzB,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,GACA,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;IAuBlE,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,GAAG,SAAS;IAI7D,cAAc,CAClB,QAAQ,EAAE,eAAe,EAAE,EAC3B,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;QACrB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;QACzB,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,GACA,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IAyB7C;;;;;;;OAOG;IACG,cAAc,CAClB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC;IAqChB;;;;;OAKG;IACH,iBAAiB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAmBrE;;;;;OAKG;IACH,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,aAAa,EAAE;IAQtD;;;;;;OAMG;IACH,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAavC;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAoBzC;;;;;;;;OAQG;IACH,oBAAoB,CAClB,QAAQ,EAAE,eAAe,EAAE,EAC3B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,GAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAO,GACxC,IAAI;IAmCP;;OAEG;IACH,sBAAsB,IAAI,IAAI;IAsoB9B;;;;;;;;OAQG;IACG,kBAAkB,CACtB,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,IAAI,CAAC;IA8BhB,OAAO,IAAI,IAAI;CAmChB"}
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsController.d.mts","sourceRoot":"","sources":["../src/AssetsController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AssetsController.d.mts","sourceRoot":"","sources":["../src/AssetsController.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
9
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");
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
- 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_shouldHideNativeToken, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
12
+ 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;
13
13
  import { BaseController } from "@metamask/base-controller";
14
14
  import { parseCaipAssetType } from "@metamask/utils";
15
15
  import { Mutex } from "async-mutex";
@@ -808,10 +808,6 @@ async function _AssetsController_updateState(response) {
808
808
  continue;
809
809
  }
810
810
  const assetChainId = extractChainId(typedAssetId);
811
- // Skip native tokens on Tempo networks
812
- if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_shouldHideNativeToken).call(this, assetChainId, typedAssetId, metadata)) {
813
- continue;
814
- }
815
811
  if (!chainIdSet.has(assetChainId)) {
816
812
  continue;
817
813
  }
@@ -845,18 +841,6 @@ async function _AssetsController_updateState(response) {
845
841
  }
846
842
  }
847
843
  return result;
848
- }, _AssetsController_shouldHideNativeToken = function _AssetsController_shouldHideNativeToken(chainId, assetId, metadata) {
849
- const TEMPO_CHAIN_IDS = ['eip155:42431', 'eip155:4217']; // Tempo Testnet (42431) and Mainnet (4217)
850
- // Check if it's a Tempo network
851
- if (!TEMPO_CHAIN_IDS.includes(chainId)) {
852
- return false;
853
- }
854
- // Check if it's a native token (either by metadata type or assetId format)
855
- const isNative = metadata.type === 'native' || assetId.includes('/slip44:');
856
- if (isNative) {
857
- return true;
858
- }
859
- return false;
860
844
  }, _AssetsController_tokenStandardToAssetType = function _AssetsController_tokenStandardToAssetType(tokenStandard) {
861
845
  switch (tokenStandard) {
862
846
  case 'native':
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsController.mjs","sourceRoot":"","sources":["../src/AssetsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n} from '@metamask/account-tree-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n ApiPlatformClient,\n BackendWebSocketServiceActions,\n BackendWebSocketServiceEvents,\n} from '@metamask/core-backend';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkEnablementControllerGetStateAction,\n NetworkEnablementControllerEvents,\n NetworkEnablementControllerState,\n} from '@metamask/network-enablement-controller';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BigNumberJS from 'bignumber.js';\nimport { isEqual } from 'lodash';\n\nimport type { AssetsControllerMethodActions } from './AssetsController-method-action-types';\nimport type {\n AbstractDataSource,\n DataSourceState,\n SubscriptionRequest,\n} from './data-sources/AbstractDataSource';\nimport { AccountsApiDataSource } from './data-sources/AccountsApiDataSource';\nimport { BackendWebsocketDataSource } from './data-sources/BackendWebsocketDataSource';\nimport { PriceDataSource } from './data-sources/PriceDataSource';\nimport type { RpcDataSourceConfig } from './data-sources/RpcDataSource';\nimport { RpcDataSource } from './data-sources/RpcDataSource';\nimport { SnapDataSource } from './data-sources/SnapDataSource';\nimport { TokenDataSource } from './data-sources/TokenDataSource';\nimport { projectLogger, createModuleLogger } from './logger';\nimport { DetectionMiddleware } from './middlewares/DetectionMiddleware';\nimport type {\n AccountId,\n AssetPreferences,\n ChainId,\n Caip19AssetId,\n AssetMetadata,\n AssetPrice,\n AssetBalance,\n AccountWithSupportedChains,\n AssetType,\n DataType,\n DataRequest,\n DataResponse,\n NextFunction,\n Middleware,\n SubscriptionResponse,\n Asset,\n AssetsControllerStateInternal,\n} from './types';\nimport { normalizeAssetId } from './utils';\n\n// ============================================================================\n// CONTROLLER CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'AssetsController' as const;\n\n/** Method names exposed as messenger actions (AssetsController:getAssets, etc.) */\nconst MESSENGER_EXPOSED_METHODS = [\n 'getAssets',\n 'getAssetsBalance',\n 'getAssetMetadata',\n 'getAssetsPrice',\n 'addCustomAsset',\n 'removeCustomAsset',\n 'getCustomAssets',\n 'hideAsset',\n 'unhideAsset',\n] as const;\n\n/** Default polling interval hint for data sources (30 seconds) */\nconst DEFAULT_POLLING_INTERVAL_MS = 30_000;\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// STATE TYPES\n// ============================================================================\n\n/**\n * State structure for AssetsController.\n *\n * All values are JSON-serializable. UI preferences (e.g. hidden) are in\n * assetPreferences, not in metadata.\n *\n * @see AssetsControllerStateInternal for the semantic type structure\n */\nexport type AssetsControllerState = {\n /** Shared metadata for all assets (stored once per asset) */\n assetsMetadata: { [assetId: string]: AssetMetadata };\n /** Per-account balance data */\n assetsBalance: { [accountId: string]: { [assetId: string]: AssetBalance } };\n /** Price data for assets */\n assetsPrice: { [assetId: string]: AssetPrice };\n /** Custom assets added by users per account (CAIP-19 asset IDs) */\n customAssets: { [accountId: string]: Caip19AssetId[] };\n /** UI preferences per asset (e.g. hidden) */\n assetPreferences: { [assetId: string]: AssetPreferences };\n};\n\n/**\n * Returns the default state for AssetsController.\n *\n * @returns The default AssetsController state with empty maps.\n */\nexport function getDefaultAssetsControllerState(): AssetsControllerState {\n return {\n assetsMetadata: {},\n assetsBalance: {},\n assetsPrice: {},\n customAssets: {},\n assetPreferences: {},\n };\n}\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\nexport type AssetsControllerGetStateAction = ControllerGetStateAction<\n typeof CONTROLLER_NAME,\n AssetsControllerState\n>;\n\nexport type AssetsControllerActions =\n | AssetsControllerGetStateAction\n | AssetsControllerMethodActions;\n\nexport type AssetsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof CONTROLLER_NAME,\n AssetsControllerState\n>;\n\nexport type AssetsControllerBalanceChangedEvent = {\n type: `${typeof CONTROLLER_NAME}:balanceChanged`;\n payload: [\n {\n accountId: AccountId;\n assetId: Caip19AssetId;\n previousAmount: string;\n newAmount: string;\n },\n ];\n};\n\nexport type AssetsControllerPriceChangedEvent = {\n type: `${typeof CONTROLLER_NAME}:priceChanged`;\n payload: [{ prices: Record<Caip19AssetId, AssetPrice> }];\n};\n\nexport type AssetsControllerAssetsDetectedEvent = {\n type: `${typeof CONTROLLER_NAME}:assetsDetected`;\n payload: [{ accountId: AccountId; assetIds: Caip19AssetId[] }];\n};\n\nexport type AssetsControllerEvents =\n | AssetsControllerStateChangeEvent\n | AssetsControllerBalanceChangedEvent\n | AssetsControllerPriceChangedEvent\n | AssetsControllerAssetsDetectedEvent;\n\ntype AllowedActions =\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | NetworkEnablementControllerGetStateAction\n // BackendWebsocketDataSource calls BackendWebSocketService\n | BackendWebSocketServiceActions;\n\ntype AllowedEvents =\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | NetworkEnablementControllerEvents\n | BackendWebSocketServiceEvents\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent;\n\nexport type AssetsControllerMessenger = Messenger<\n typeof CONTROLLER_NAME,\n AssetsControllerActions | AllowedActions,\n AssetsControllerEvents | AllowedEvents\n>;\n\n// ============================================================================\n// CONTROLLER OPTIONS\n// ============================================================================\n\nexport type AssetsControllerOptions = {\n messenger: AssetsControllerMessenger;\n state?: Partial<AssetsControllerState>;\n /** Default polling interval hint passed to data sources (ms) */\n defaultUpdateInterval?: number;\n /** Function to determine if the controller is enabled. Defaults to true. */\n isEnabled?: () => boolean;\n /**\n * API client for balance/price/metadata. The controller instantiates data sources\n * and uses them directly when this is provided.\n */\n queryApiClient: ApiPlatformClient;\n /** Optional configuration for RpcDataSource. */\n rpcDataSourceConfig?: RpcDataSourceConfig;\n};\n\n// ============================================================================\n// STATE METADATA\n// ============================================================================\n\nconst stateMetadata: StateMetadata<AssetsControllerState> = {\n assetsMetadata: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetsBalance: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetsPrice: {\n persist: false,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n customAssets: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetPreferences: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\nfunction extractChainId(assetId: Caip19AssetId): ChainId {\n const parsed = parseCaipAssetType(assetId);\n return parsed.chainId;\n}\n\n/**\n * Normalizes all asset IDs in a DataResponse.\n * This is applied at the controller level to ensure consistent state\n * regardless of how data sources format their asset IDs.\n *\n * @param response - The DataResponse to normalize.\n * @returns The normalized DataResponse with checksummed EVM addresses.\n */\nfunction normalizeResponse(response: DataResponse): DataResponse {\n const normalized: DataResponse = {};\n\n if (response.assetsMetadata) {\n normalized.assetsMetadata = {};\n for (const [assetId, metadata] of Object.entries(response.assetsMetadata)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsMetadata[normalizedId] = metadata;\n }\n }\n\n if (response.assetsPrice) {\n normalized.assetsPrice = {};\n for (const [assetId, price] of Object.entries(response.assetsPrice)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsPrice[normalizedId] = price;\n }\n }\n\n if (response.assetsBalance) {\n normalized.assetsBalance = {};\n for (const [accountId, balances] of Object.entries(\n response.assetsBalance,\n )) {\n normalized.assetsBalance[accountId] = {};\n for (const [assetId, balance] of Object.entries(balances)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsBalance[accountId][normalizedId] = balance;\n }\n }\n }\n\n // Preserve detectedAssets with normalized asset IDs\n if (response.detectedAssets) {\n normalized.detectedAssets = {};\n for (const [accountId, assetIds] of Object.entries(\n response.detectedAssets,\n )) {\n normalized.detectedAssets[accountId] = assetIds.map((assetId) =>\n normalizeAssetId(assetId),\n );\n }\n }\n\n // Preserve errors (chain IDs don't need normalization)\n if (response.errors) {\n normalized.errors = { ...response.errors };\n }\n\n return normalized;\n}\n\n// ============================================================================\n// CONTROLLER IMPLEMENTATION\n// ============================================================================\n\n/**\n * AssetsController provides a unified interface for managing asset balances\n * across all blockchain networks (EVM and non-EVM) and all asset types.\n *\n * ## Core Responsibilities\n *\n * 1. **One-Time Fetch (Sync)**: For initial load, force refresh, or on-demand queries.\n * Uses `getAssets()`, `getAssetsBalance()`, etc. with `forceUpdate: true`.\n *\n * 2. **Async Subscriptions**: Subscribes to data sources for ongoing updates.\n * Data sources push updates via callbacks; the controller updates state.\n *\n * 3. **Dynamic Source Selection**: Routes requests to appropriate data sources\n * based on which chains they support. When active chains change, the controller\n * dynamically adjusts subscriptions.\n *\n * 4. **Keyring Lifecycle**: Listens to KeyringController unlock/lock events to\n * start/stop subscriptions when the wallet is unlocked or locked.\n *\n * ## Architecture\n *\n * - Data sources declare their supported chains (async, can change over time)\n * - Data sources are responsible for their own update mechanisms (WebSocket, polling, events)\n * - The controller does NOT manage polling - it simply receives pushed updates\n */\nexport class AssetsController extends BaseController<\n typeof CONTROLLER_NAME,\n AssetsControllerState,\n AssetsControllerMessenger\n> {\n /** Whether the controller is enabled */\n readonly #isEnabled: boolean;\n\n /** Default update interval hint passed to data sources */\n readonly #defaultUpdateInterval: number;\n\n readonly #controllerMutex = new Mutex();\n\n /**\n * Active balance subscriptions keyed by account ID.\n * Each account has one logical subscription that may span multiple data sources.\n * For example, if WebSocket covers chains A,B and RPC covers chain C,\n * the account subscribes to both data sources for its chains.\n */\n readonly #activeSubscriptions: Map<string, SubscriptionResponse> = new Map();\n\n /** Currently enabled chains from NetworkEnablementController */\n #enabledChains: Set<ChainId> = new Set();\n\n /**\n * Get the currently selected accounts from AccountTreeController.\n * This includes all accounts in the same group as the selected account\n * (EVM, Bitcoin, Solana, Tron, etc. that belong to the same logical account group).\n *\n * @returns Array of InternalAccount objects from the selected account group.\n */\n get #selectedAccounts(): InternalAccount[] {\n return this.messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n }\n\n readonly #backendWebsocketDataSource: BackendWebsocketDataSource;\n\n readonly #accountsApiDataSource: AccountsApiDataSource;\n\n readonly #snapDataSource: SnapDataSource;\n\n readonly #rpcDataSource: RpcDataSource;\n\n /**\n * Subscription balance data sources in assignment priority order (first that supports a chain gets it).\n *\n * @returns The four balance data source instances in priority order.\n */\n get #subscriptionBalanceDataSources(): [\n BackendWebsocketDataSource,\n AccountsApiDataSource,\n SnapDataSource,\n RpcDataSource,\n ] {\n return [\n this.#backendWebsocketDataSource,\n this.#accountsApiDataSource,\n this.#snapDataSource,\n this.#rpcDataSource,\n ];\n }\n\n readonly #priceDataSource: PriceDataSource;\n\n readonly #detectionMiddleware: DetectionMiddleware;\n\n readonly #tokenDataSource: TokenDataSource;\n\n constructor({\n messenger,\n state = {},\n defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS,\n isEnabled = (): boolean => true,\n queryApiClient,\n rpcDataSourceConfig,\n }: AssetsControllerOptions) {\n super({\n name: CONTROLLER_NAME,\n messenger,\n metadata: stateMetadata,\n state: {\n ...getDefaultAssetsControllerState(),\n ...state,\n },\n });\n\n this.#isEnabled = isEnabled();\n this.#defaultUpdateInterval = defaultUpdateInterval;\n const rpcConfig = rpcDataSourceConfig ?? {};\n\n const onActiveChainsUpdated = (\n dataSourceName: string,\n chains: ChainId[],\n previousChains: ChainId[],\n ): void =>\n this.handleActiveChainsUpdate(dataSourceName, chains, previousChains);\n\n this.#backendWebsocketDataSource = new BackendWebsocketDataSource({\n messenger: this.messenger,\n queryApiClient,\n onActiveChainsUpdated,\n });\n this.#accountsApiDataSource = new AccountsApiDataSource({\n queryApiClient,\n onActiveChainsUpdated,\n });\n this.#snapDataSource = new SnapDataSource({\n messenger: this.messenger,\n onActiveChainsUpdated,\n });\n this.#rpcDataSource = new RpcDataSource({\n messenger: this.messenger,\n onActiveChainsUpdated,\n ...rpcConfig,\n });\n this.#tokenDataSource = new TokenDataSource({\n queryApiClient,\n });\n this.#priceDataSource = new PriceDataSource({\n queryApiClient,\n });\n this.#detectionMiddleware = new DetectionMiddleware();\n\n if (!this.#isEnabled) {\n log('AssetsController is disabled, skipping initialization');\n return;\n }\n\n log('Initializing AssetsController', {\n defaultUpdateInterval: this.#defaultUpdateInterval,\n });\n\n this.#initializeState();\n this.#subscribeToEvents();\n this.#registerActionHandlers();\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n #initializeState(): void {\n const { enabledNetworkMap } = this.messenger.call(\n 'NetworkEnablementController:getState',\n );\n this.#enabledChains = this.#extractEnabledChains(enabledNetworkMap);\n\n log('Initialized state', {\n enabledNetworkMap,\n enabledChains: this.#enabledChains,\n });\n }\n\n /**\n * Extract enabled chains from enabledNetworkMap.\n * Returns CAIP-2 chain IDs for all enabled networks across all namespaces.\n *\n * Note: For EIP155 (EVM) chains, the reference is normalized to decimal format\n * to ensure consistency with CAIP-2 standard and API responses.\n *\n * @param enabledNetworkMap - The enabled network map from NetworkEnablementController.\n * @returns Set of CAIP-2 chain IDs for all enabled networks.\n */\n #extractEnabledChains(\n enabledNetworkMap: NetworkEnablementControllerState['enabledNetworkMap'],\n ): Set<ChainId> {\n const chains = new Set<ChainId>();\n\n for (const [namespace, networks] of Object.entries(enabledNetworkMap)) {\n for (const [reference, isEnabled] of Object.entries(networks)) {\n if (isEnabled) {\n // Check if reference is already a full CAIP-2 chain ID (contains colon)\n if (reference.includes(':')) {\n // Already a full chain ID, use as-is\n chains.add(reference as ChainId);\n } else {\n // Normalize EIP155 chain references from hex to decimal (CAIP-2 standard)\n const normalizedReference = this.#normalizeChainReference(\n namespace,\n reference,\n );\n chains.add(`${namespace}:${normalizedReference}`);\n }\n }\n }\n }\n return chains;\n }\n\n /**\n * Normalize chain reference to CAIP-2 standard format.\n * For EIP155, converts hex chain IDs to decimal.\n *\n * @param namespace - The chain namespace (e.g., \"eip155\").\n * @param reference - The chain reference (e.g., \"0x1\" or \"1\").\n * @returns The normalized chain reference in decimal format.\n */\n #normalizeChainReference(namespace: string, reference: string): string {\n if (namespace === 'eip155' && reference.startsWith('0x')) {\n // Convert hex to decimal for EIP155 chains\n return parseInt(reference, 16).toString();\n }\n return reference;\n }\n\n #subscribeToEvents(): void {\n // Subscribe to account group changes (when user switches between account groups like Account 1 -> Account 2)\n this.messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n () => {\n this.#handleAccountGroupChanged().catch(console.error);\n },\n );\n\n // Subscribe to network enablement changes (only enabledNetworkMap)\n this.messenger.subscribe(\n 'NetworkEnablementController:stateChange',\n ({ enabledNetworkMap }) => {\n this.#handleEnabledNetworksChanged(enabledNetworkMap).catch(\n console.error,\n );\n },\n );\n\n // Keyring lifecycle: start when unlocked, stop when locked\n this.messenger.subscribe('KeyringController:unlock', () => this.#start());\n this.messenger.subscribe('KeyringController:lock', () => this.#stop());\n }\n\n #registerActionHandlers(): void {\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n // ============================================================================\n // DATA SOURCE CHAIN MANAGEMENT\n // ============================================================================\n\n /**\n * Handle when a data source's supported chains change.\n * Used to refresh balance subscriptions and run a one-time fetch when a new chain is supported.\n *\n * - On any add/remove: re-subscribes to data sources so chain assignment stays correct.\n * - When chains are added: fetches balances for the new chains (for selected accounts on enabled networks).\n *\n * Controller does not store chains; sources report via this callback. previousChains is required for diff.\n *\n * @param dataSourceId - The identifier of the data source reporting the change.\n * @param activeChains - Currently active (supported and available) chain IDs for this source.\n * @param previousChains - Previous chains; used to compute added/removed.\n */\n handleActiveChainsUpdate(\n dataSourceId: string,\n activeChains: ChainId[],\n previousChains: ChainId[],\n ): void {\n log('Data source active chains changed', {\n dataSourceId,\n chainCount: activeChains.length,\n chains: activeChains,\n });\n\n const previous: ChainId[] = previousChains;\n\n const previousSet = new Set(previous);\n const addedChains = activeChains.filter((ch) => !previousSet.has(ch));\n const removedChains = previous.filter((ch) => !activeChains.includes(ch));\n\n if (addedChains.length > 0 || removedChains.length > 0) {\n // Refresh subscriptions to use updated data source availability\n this.#subscribeAssets();\n }\n\n // If chains were added and we have selected accounts, do one-time fetch\n if (addedChains.length > 0 && this.#selectedAccounts.length > 0) {\n const addedEnabledChains = addedChains.filter((chain) =>\n this.#enabledChains.has(chain),\n );\n if (addedEnabledChains.length > 0) {\n log('Fetching balances for newly added chains', { addedEnabledChains });\n this.getAssets(this.#selectedAccounts, {\n chainIds: addedEnabledChains,\n forceUpdate: true,\n }).catch((error) => {\n log('Failed to fetch balance for added chains', { error });\n });\n }\n }\n }\n\n // ============================================================================\n // MIDDLEWARE EXECUTION\n // ============================================================================\n\n /**\n * Execute middlewares with request/response context.\n *\n * @param middlewares - Middlewares to execute in order.\n * @param request - The data request.\n * @param initialResponse - Optional initial response (for enriching existing data).\n * @returns The final DataResponse after all middlewares have processed.\n */\n async #executeMiddlewares(\n middlewares: Middleware[],\n request: DataRequest,\n initialResponse: DataResponse = {},\n ): Promise<DataResponse> {\n const chain = middlewares.reduceRight<NextFunction>(\n (next, middleware) =>\n async (\n ctx,\n ): Promise<{\n request: DataRequest;\n response: DataResponse;\n getAssetsState: () => AssetsControllerStateInternal;\n }> => {\n try {\n return await middleware(ctx, next);\n } catch (error) {\n console.error('[AssetsController] Middleware failed:', error);\n return next(ctx);\n }\n },\n async (ctx) => ctx,\n );\n\n const result = await chain({\n request,\n response: initialResponse,\n getAssetsState: () => this.state as AssetsControllerStateInternal,\n });\n return result.response;\n }\n\n // ============================================================================\n // PUBLIC API: QUERY METHODS\n // ============================================================================\n\n async getAssets(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n dataTypes?: DataType[];\n },\n ): Promise<Record<AccountId, Record<Caip19AssetId, Asset>>> {\n const chainIds = options?.chainIds ?? [...this.#enabledChains];\n const assetTypes = options?.assetTypes ?? ['fungible'];\n const dataTypes = options?.dataTypes ?? ['balance', 'metadata', 'price'];\n\n // Collect custom assets for all requested accounts\n const customAssets: Caip19AssetId[] = [];\n for (const account of accounts) {\n const accountCustomAssets = this.getCustomAssets(account.id);\n customAssets.push(...accountCustomAssets);\n }\n\n if (options?.forceUpdate) {\n const request = this.#buildDataRequest(accounts, chainIds, {\n assetTypes,\n dataTypes,\n customAssets: customAssets.length > 0 ? customAssets : undefined,\n forceUpdate: true,\n });\n const response = await this.#executeMiddlewares(\n [\n this.#accountsApiDataSource.assetsMiddleware,\n this.#snapDataSource.assetsMiddleware,\n this.#rpcDataSource.assetsMiddleware,\n this.#detectionMiddleware.assetsMiddleware,\n this.#tokenDataSource.assetsMiddleware,\n this.#priceDataSource.assetsMiddleware,\n ],\n request,\n );\n await this.#updateState(response);\n }\n\n return this.#getAssetsFromState(accounts, chainIds, assetTypes);\n }\n\n async getAssetsBalance(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n },\n ): Promise<Record<AccountId, Record<Caip19AssetId, AssetBalance>>> {\n // Reuse getAssets with dataTypes: ['balance'] only\n const assets = await this.getAssets(accounts, {\n chainIds: options?.chainIds,\n assetTypes: options?.assetTypes,\n forceUpdate: options?.forceUpdate,\n dataTypes: ['balance', 'metadata'],\n });\n\n // Extract just the balance from each asset\n const result: Record<AccountId, Record<Caip19AssetId, AssetBalance>> = {};\n for (const [accountId, accountAssets] of Object.entries(assets)) {\n result[accountId] = {};\n for (const [assetId, asset] of Object.entries(accountAssets)) {\n if (asset.balance) {\n result[accountId][assetId as Caip19AssetId] = asset.balance;\n }\n }\n }\n\n return result;\n }\n\n getAssetMetadata(assetId: Caip19AssetId): AssetMetadata | undefined {\n return this.state.assetsMetadata[assetId] as AssetMetadata | undefined;\n }\n\n async getAssetsPrice(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n },\n ): Promise<Record<Caip19AssetId, AssetPrice>> {\n const assets = await this.getAssets(accounts, {\n chainIds: options?.chainIds,\n assetTypes: options?.assetTypes,\n forceUpdate: options?.forceUpdate,\n dataTypes: ['price'],\n });\n\n // Extract just the price from each asset (flattened across accounts)\n const result: Record<Caip19AssetId, AssetPrice> = {};\n for (const accountAssets of Object.values(assets)) {\n for (const [assetId, asset] of Object.entries(accountAssets)) {\n if (asset.price) {\n result[assetId as Caip19AssetId] = asset.price;\n }\n }\n }\n\n return result;\n }\n\n // ============================================================================\n // CUSTOM ASSETS MANAGEMENT\n // ============================================================================\n\n /**\n * Add a custom asset for an account.\n * Custom assets are included in subscription and fetch operations.\n * Adding a custom asset also unhides it if it was previously hidden.\n *\n * @param accountId - The account ID to add the custom asset for.\n * @param assetId - The CAIP-19 asset ID to add.\n */\n async addCustomAsset(\n accountId: AccountId,\n assetId: Caip19AssetId,\n ): Promise<void> {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Adding custom asset', { accountId, assetId: normalizedAssetId });\n\n this.update((state) => {\n const customAssets = state.customAssets as Record<string, string[]>;\n if (!customAssets[accountId]) {\n customAssets[accountId] = [];\n }\n\n // Only add if not already present\n if (!customAssets[accountId].includes(normalizedAssetId)) {\n customAssets[accountId].push(normalizedAssetId);\n }\n\n // Unhide the asset if it was hidden (via assetPreferences)\n const prefs = state.assetPreferences[normalizedAssetId];\n if (prefs?.hidden) {\n delete prefs.hidden;\n if (Object.keys(prefs).length === 0) {\n delete state.assetPreferences[normalizedAssetId];\n }\n }\n });\n\n // Fetch data for the newly added custom asset\n const account = this.#selectedAccounts.find((a) => a.id === accountId);\n if (account) {\n const chainId = extractChainId(normalizedAssetId);\n await this.getAssets([account], {\n chainIds: [chainId],\n forceUpdate: true,\n });\n }\n }\n\n /**\n * Remove a custom asset from an account.\n *\n * @param accountId - The account ID to remove the custom asset from.\n * @param assetId - The CAIP-19 asset ID to remove.\n */\n removeCustomAsset(accountId: AccountId, assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Removing custom asset', { accountId, assetId: normalizedAssetId });\n\n this.update((state) => {\n if (state.customAssets[accountId]) {\n state.customAssets[accountId] = state.customAssets[accountId].filter(\n (id) => id !== normalizedAssetId,\n );\n\n // Clean up empty arrays\n if (state.customAssets[accountId].length === 0) {\n delete state.customAssets[accountId];\n }\n }\n });\n }\n\n /**\n * Get all custom assets for an account.\n *\n * @param accountId - The account ID to get custom assets for.\n * @returns Array of CAIP-19 asset IDs for the account's custom assets.\n */\n getCustomAssets(accountId: AccountId): Caip19AssetId[] {\n return this.state.customAssets[accountId] ?? [];\n }\n\n // ============================================================================\n // HIDDEN ASSETS MANAGEMENT\n // ============================================================================\n\n /**\n * Hide an asset globally.\n * Hidden assets are excluded from the asset list returned by getAssets.\n * The hidden state is stored in assetPreferences.\n *\n * @param assetId - The CAIP-19 asset ID to hide.\n */\n hideAsset(assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Hiding asset', { assetId: normalizedAssetId });\n\n this.update((state) => {\n if (!state.assetPreferences[normalizedAssetId]) {\n state.assetPreferences[normalizedAssetId] = {};\n }\n state.assetPreferences[normalizedAssetId].hidden = true;\n });\n }\n\n /**\n * Unhide an asset globally.\n *\n * @param assetId - The CAIP-19 asset ID to unhide.\n */\n unhideAsset(assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Unhiding asset', { assetId: normalizedAssetId });\n\n this.update((state) => {\n const prefs = state.assetPreferences[normalizedAssetId];\n if (prefs) {\n delete prefs.hidden;\n if (Object.keys(prefs).length === 0) {\n delete state.assetPreferences[normalizedAssetId];\n }\n }\n });\n }\n\n // ============================================================================\n // SUBSCRIPTIONS\n // ============================================================================\n\n /**\n * Subscribe to price updates for all assets held by the given accounts.\n * Polls PriceDataSource which fetches prices from balance state.\n *\n * @param accounts - Accounts to subscribe price updates for.\n * @param chainIds - Chain IDs to filter prices for.\n * @param options - Subscription options.\n * @param options.updateInterval - Polling interval in ms.\n */\n subscribeAssetsPrice(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n options: { updateInterval?: number } = {},\n ): void {\n const { updateInterval = this.#defaultUpdateInterval } = options;\n const subscriptionKey = 'ds:PriceDataSource';\n\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n const isUpdate = existingSubscription !== undefined;\n\n const subscribeReq: SubscriptionRequest = {\n request: this.#buildDataRequest(accounts, chainIds, {\n dataTypes: ['price'],\n updateInterval,\n }),\n subscriptionId: subscriptionKey,\n isUpdate,\n onAssetsUpdate: (response) =>\n this.handleAssetsUpdate(response, 'PriceDataSource'),\n getAssetsState: () => this.state,\n };\n\n this.#priceDataSource.subscribe(subscribeReq).catch(console.error);\n\n // Track subscription\n const subscription: SubscriptionResponse = {\n chains: chainIds,\n accountId: subscriptionKey,\n assetTypes: ['fungible'],\n dataTypes: ['price'],\n unsubscribe: () => {\n this.#activeSubscriptions.delete(subscriptionKey);\n },\n };\n\n this.#activeSubscriptions.set(subscriptionKey, subscription);\n }\n\n /**\n * Unsubscribe from price updates.\n */\n unsubscribeAssetsPrice(): void {\n const subscriptionKey = 'ds:PriceDataSource';\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n\n if (!existingSubscription) {\n return;\n }\n this.#priceDataSource.unsubscribe(subscriptionKey).catch(console.error);\n existingSubscription.unsubscribe();\n }\n\n // ============================================================================\n // STATE MANAGEMENT\n // ============================================================================\n\n async #updateState(response: DataResponse): Promise<void> {\n // Normalize asset IDs (checksum EVM addresses) before storing in state\n const normalizedResponse = normalizeResponse(response);\n\n const releaseLock = await this.#controllerMutex.acquire();\n\n try {\n const previousState = this.state;\n const previousPrices = { ...this.state.assetsPrice };\n // Use detectedAssets from response (assets without metadata)\n const detectedAssets: Record<AccountId, Caip19AssetId[]> =\n normalizedResponse.detectedAssets ?? {};\n\n // Track actual changes for logging\n const changedBalances: {\n accountId: string;\n assetId: string;\n oldAmount: string | undefined;\n newAmount: string;\n }[] = [];\n const changedMetadata: string[] = [];\n\n this.update((state) => {\n // Use type assertions to avoid deep type instantiation issues with Immer Draft types\n const metadata = state.assetsMetadata as Record<string, AssetMetadata>;\n const balances = state.assetsBalance as Record<\n string,\n Record<string, AssetBalance>\n >;\n const prices = state.assetsPrice as Record<string, AssetPrice>;\n\n if (normalizedResponse.assetsMetadata) {\n for (const [key, value] of Object.entries(\n normalizedResponse.assetsMetadata,\n )) {\n if (\n !isEqual(\n previousState.assetsMetadata[key as Caip19AssetId],\n value,\n )\n ) {\n changedMetadata.push(key);\n }\n metadata[key] = value;\n }\n }\n\n if (normalizedResponse.assetsBalance) {\n for (const [accountId, accountBalances] of Object.entries(\n normalizedResponse.assetsBalance,\n )) {\n const previousBalances =\n previousState.assetsBalance[accountId] ?? {};\n\n if (!balances[accountId]) {\n balances[accountId] = {};\n }\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n const previousBalance = previousBalances[\n assetId as Caip19AssetId\n ] as { amount: string } | undefined;\n const balanceData = balance as { amount: string };\n const newAmount = balanceData.amount;\n const oldAmount = previousBalance?.amount;\n\n // Track if balance actually changed\n if (oldAmount !== newAmount) {\n changedBalances.push({\n accountId,\n assetId,\n oldAmount,\n newAmount,\n });\n }\n }\n\n Object.assign(balances[accountId], accountBalances);\n }\n }\n\n // Update prices in state\n if (normalizedResponse.assetsPrice) {\n for (const [key, value] of Object.entries(\n normalizedResponse.assetsPrice,\n )) {\n prices[key] = value;\n }\n }\n });\n\n // Calculate changed prices\n const changedPriceAssets: string[] = normalizedResponse.assetsPrice\n ? Object.keys(normalizedResponse.assetsPrice).filter(\n (assetId) =>\n !isEqual(\n previousPrices[assetId as Caip19AssetId],\n normalizedResponse.assetsPrice?.[assetId as Caip19AssetId],\n ),\n )\n : [];\n\n // Log only actual changes\n if (\n changedBalances.length > 0 ||\n changedMetadata.length > 0 ||\n changedPriceAssets.length > 0\n ) {\n log('State updated', {\n changedBalances:\n changedBalances.length > 0 ? changedBalances : undefined,\n changedMetadataCount:\n changedMetadata.length > 0 ? changedMetadata.length : undefined,\n changedPricesCount:\n changedPriceAssets.length > 0\n ? changedPriceAssets.length\n : undefined,\n newAssets:\n Object.keys(detectedAssets).length > 0\n ? Object.entries(detectedAssets).map(([accountId, assets]) => ({\n accountId,\n assets,\n }))\n : undefined,\n });\n }\n\n // Publish balance changed events\n for (const change of changedBalances) {\n this.messenger.publish('AssetsController:balanceChanged', {\n accountId: change.accountId,\n assetId: change.assetId as Caip19AssetId,\n previousAmount: change.oldAmount ?? '0',\n newAmount: change.newAmount,\n });\n }\n\n // Publish price changed event with full price data\n if (changedPriceAssets.length > 0 && normalizedResponse.assetsPrice) {\n // Build prices object with only changed prices\n const changedPrices: Record<Caip19AssetId, AssetPrice> = {};\n for (const assetId of changedPriceAssets) {\n const price =\n normalizedResponse.assetsPrice[assetId as Caip19AssetId];\n if (price) {\n changedPrices[assetId as Caip19AssetId] = price;\n }\n }\n this.messenger.publish('AssetsController:priceChanged', {\n prices: changedPrices,\n });\n }\n\n // Publish assets detected events\n for (const [accountId, assetIds] of Object.entries(detectedAssets)) {\n if (assetIds.length > 0) {\n this.messenger.publish('AssetsController:assetsDetected', {\n accountId,\n assetIds,\n });\n }\n }\n } finally {\n releaseLock();\n }\n }\n\n #getAssetsFromState(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n assetTypes: AssetType[],\n ): Record<AccountId, Record<Caip19AssetId, Asset>> {\n const result: Record<AccountId, Record<Caip19AssetId, Asset>> = {};\n // Convert to Sets for O(1) lookups\n const chainIdSet = new Set(chainIds);\n const assetTypeSet = new Set(assetTypes);\n\n for (const account of accounts) {\n result[account.id] = {};\n\n const accountBalances = this.state.assetsBalance[account.id] ?? {};\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n const typedAssetId = assetId as Caip19AssetId;\n\n const metadataRaw = this.state.assetsMetadata[typedAssetId];\n\n // Skip assets without metadata\n if (!metadataRaw) {\n continue;\n }\n\n const metadata = metadataRaw;\n\n // Skip hidden assets (assetPreferences)\n const prefs = this.state.assetPreferences[typedAssetId];\n if (prefs?.hidden) {\n continue;\n }\n\n const assetChainId = extractChainId(typedAssetId);\n\n // Skip native tokens on Tempo networks\n if (this.#shouldHideNativeToken(assetChainId, typedAssetId, metadata)) {\n continue;\n }\n\n if (!chainIdSet.has(assetChainId)) {\n continue;\n }\n\n // Filter by asset type\n const tokenAssetType = this.#tokenStandardToAssetType(metadata.type);\n if (!assetTypeSet.has(tokenAssetType)) {\n continue;\n }\n\n const typedBalance = balance;\n const priceRaw = this.state.assetsPrice[typedAssetId];\n const price: AssetPrice = priceRaw ?? {\n price: 0,\n lastUpdated: 0,\n };\n\n // Compute fiat value using BigNumber for precision\n // Note: typedBalance.amount is already in human-readable format (e.g., \"1\" for 1 ETH)\n // so we do NOT divide by 10^decimals here\n const balanceAmount = new BigNumberJS(typedBalance.amount || '0');\n const fiatValue = balanceAmount\n .multipliedBy(price.price || 0)\n .toNumber();\n\n const asset: Asset = {\n id: typedAssetId,\n chainId: assetChainId,\n balance: typedBalance,\n metadata,\n price,\n fiatValue,\n };\n\n result[account.id][typedAssetId] = asset;\n }\n }\n\n return result;\n }\n\n /**\n * Determines if a native token should be hidden on specific networks.\n *\n * @param chainId - The CAIP-2 chain ID (e.g., \"eip155:42431\").\n * @param assetId - The CAIP-19 asset ID (e.g., \"eip155:42431/slip44:60\").\n * @param metadata - The asset metadata.\n * @returns True if the token should be hidden, false otherwise.\n */\n #shouldHideNativeToken(\n chainId: ChainId,\n assetId: Caip19AssetId,\n metadata: AssetMetadata,\n ): boolean {\n const TEMPO_CHAIN_IDS = ['eip155:42431', 'eip155:4217']; // Tempo Testnet (42431) and Mainnet (4217)\n\n // Check if it's a Tempo network\n if (!TEMPO_CHAIN_IDS.includes(chainId)) {\n return false;\n }\n\n // Check if it's a native token (either by metadata type or assetId format)\n const isNative =\n metadata.type === 'native' || assetId.includes('/slip44:');\n\n if (isNative) {\n return true;\n }\n\n\n return false;\n }\n\n /**\n * Maps a token standard to its corresponding asset type.\n *\n * @param tokenStandard - The token standard from metadata.\n * @returns The corresponding asset type.\n */\n #tokenStandardToAssetType(tokenStandard: string): AssetType {\n switch (tokenStandard) {\n case 'native':\n case 'erc20':\n case 'spl':\n return 'fungible';\n case 'erc721':\n return 'nft';\n case 'erc1155':\n // ERC1155 can be either fungible or non-fungible, treat as collectible\n return 'collectible';\n default:\n // Unknown standards default to fungible\n return 'fungible';\n }\n }\n\n // ============================================================================\n // START / STOP\n // ============================================================================\n\n /**\n * Start asset tracking: subscribe to updates and fetch current balances.\n * Called when app opens, account changes, or keyring unlocks.\n */\n #start(): void {\n log('Starting asset tracking', {\n selectedAccountCount: this.#selectedAccounts.length,\n enabledChainCount: this.#enabledChains.size,\n });\n\n this.#subscribeAssets();\n if (this.#selectedAccounts.length > 0) {\n this.getAssets(this.#selectedAccounts, {\n chainIds: [...this.#enabledChains],\n forceUpdate: true,\n }).catch((error) => {\n log('Failed to fetch assets', error);\n });\n }\n }\n\n /**\n * Stop asset tracking: unsubscribe from all updates.\n * Called when app closes or keyring locks.\n */\n #stop(): void {\n log('Stopping asset tracking', {\n activeSubscriptionCount: this.#activeSubscriptions.size,\n hasPriceSubscription: this.#activeSubscriptions.has('ds:PriceDataSource'),\n });\n\n // Stop price subscription first (uses direct messenger call)\n this.unsubscribeAssetsPrice();\n\n // Stop balance subscriptions by properly notifying data sources via messenger\n // This ensures data sources stop their polling timers\n // Convert to array first to avoid modifying map during iteration\n const subscriptionKeys = [...this.#activeSubscriptions.keys()];\n for (const subscriptionKey of subscriptionKeys) {\n if (subscriptionKey.startsWith('ds:')) {\n const sourceId = subscriptionKey.slice(3);\n const source = this.#subscriptionBalanceDataSources.find(\n (ds) => ds.getName() === sourceId,\n );\n if (source) {\n this.#unsubscribeDataSource(source);\n }\n }\n }\n this.#activeSubscriptions.clear();\n }\n\n /**\n * Subscribe to asset updates for all selected accounts.\n */\n #subscribeAssets(): void {\n if (this.#selectedAccounts.length === 0) {\n return;\n }\n\n // Subscribe to balance updates (batched by data source)\n this.#subscribeAssetsBalance(this.#selectedAccounts, [\n ...this.#enabledChains,\n ]);\n\n // Subscribe to price updates for all assets held by selected accounts\n this.subscribeAssetsPrice(this.#selectedAccounts, [...this.#enabledChains]);\n }\n\n /**\n * Subscribe to balance updates for the given accounts and chains.\n *\n * Strategy to minimize data source calls:\n * 1. Collect all chains to subscribe based on enabled networks\n * 2. Map chains to accounts based on their scopes\n * 3. Split by data source (ordered by priority) - each data source gets ONE subscription\n *\n * This ensures we make minimal subscriptions to each data source while covering\n * all accounts and chains.\n *\n * @param accounts - Accounts to subscribe balance updates for.\n * @param chainIds - Chain IDs to subscribe for.\n */\n #subscribeAssetsBalance(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n ): void {\n const chainToAccounts = this.#buildChainToAccountsMap(\n accounts,\n new Set(chainIds),\n );\n const remainingChains = new Set(chainToAccounts.keys());\n\n for (const source of this.#subscriptionBalanceDataSources) {\n const availableChains = new Set(source.getActiveChainsSync());\n const assignedChains: ChainId[] = [];\n\n for (const chainId of remainingChains) {\n if (availableChains.has(chainId)) {\n assignedChains.push(chainId);\n remainingChains.delete(chainId);\n }\n }\n\n if (assignedChains.length === 0) {\n this.#unsubscribeDataSource(source);\n continue;\n }\n\n const seenIds = new Set<string>();\n const accountsForSource = assignedChains\n .flatMap((chainId) => chainToAccounts.get(chainId) ?? [])\n .filter(\n (account) =>\n !seenIds.has(account.id) && (seenIds.add(account.id), true),\n );\n if (accountsForSource.length > 0) {\n this.#subscribeDataSource(source, accountsForSource, assignedChains);\n }\n }\n }\n\n /**\n * Build a mapping of chainId -> accounts that support that chain.\n * Only includes chains that are in the chainsToSubscribe set.\n *\n * @param accounts - Array of accounts to build mapping for.\n * @param chainsToSubscribe - Set of chain IDs to include in the mapping.\n * @returns Map of chainId to array of accounts that support that chain.\n */\n #buildChainToAccountsMap(\n accounts: InternalAccount[],\n chainsToSubscribe: Set<ChainId>,\n ): Map<ChainId, InternalAccount[]> {\n const chainToAccounts = new Map<ChainId, InternalAccount[]>();\n for (const account of accounts) {\n for (const chainId of this.#getEnabledChainsForAccount(account)) {\n if (!chainsToSubscribe.has(chainId)) {\n continue;\n }\n let list = chainToAccounts.get(chainId);\n if (!list) {\n list = [];\n chainToAccounts.set(chainId, list);\n }\n list.push(account);\n }\n }\n return chainToAccounts;\n }\n\n /**\n * Subscribe to a specific data source with accounts and chains.\n * Uses the data source name as the subscription key for batching.\n *\n * @param source - The balance data source instance.\n * @param accounts - Array of accounts to subscribe for.\n * @param chains - Array of chain IDs to subscribe for.\n */\n #subscribeDataSource(\n source: AbstractDataSource<string, DataSourceState>,\n accounts: InternalAccount[],\n chains: ChainId[],\n ): void {\n const sourceId = source.getName();\n const subscriptionKey = `ds:${sourceId}`;\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n const isUpdate = existingSubscription !== undefined;\n\n log('Subscribe to data source', {\n sourceId,\n subscriptionKey,\n isUpdate,\n accountCount: accounts.length,\n chainCount: chains.length,\n });\n\n const subscribeReq: SubscriptionRequest = {\n request: this.#buildDataRequest(accounts, chains, {\n assetTypes: ['fungible'],\n dataTypes: ['balance'],\n updateInterval: this.#defaultUpdateInterval,\n }),\n subscriptionId: subscriptionKey,\n isUpdate,\n onAssetsUpdate: (response) => this.handleAssetsUpdate(response, sourceId),\n getAssetsState: () => this.state,\n };\n\n source.subscribe(subscribeReq).catch((error) => {\n console.error(\n `[AssetsController] Failed to subscribe to '${sourceId}':`,\n error,\n );\n });\n\n // Track subscription\n const subscription: SubscriptionResponse = {\n chains,\n accountId: subscriptionKey,\n assetTypes: ['fungible'],\n dataTypes: ['balance'],\n unsubscribe: () => {\n this.#activeSubscriptions.delete(subscriptionKey);\n },\n };\n\n this.#activeSubscriptions.set(subscriptionKey, subscription);\n }\n\n /**\n * Unsubscribe from a data source if we have an active subscription.\n *\n * @param source - The balance data source instance to unsubscribe from.\n */\n #unsubscribeDataSource(\n source: AbstractDataSource<string, DataSourceState>,\n ): void {\n const subscriptionKey = `ds:${source.getName()}`;\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n\n if (existingSubscription) {\n source.unsubscribe(subscriptionKey).catch(() => undefined);\n existingSubscription.unsubscribe();\n }\n }\n\n // ============================================================================\n // HELPERS\n // ============================================================================\n\n /**\n * Build a DataRequest with accountsWithSupportedChains (enabled chains ∩ account scope ∩ requested chainIds).\n *\n * @param accounts - Accounts to include.\n * @param chainIds - Requested chain IDs (e.g. enabled chains or subset).\n * @param partial - Rest of the request (dataTypes, assetTypes, etc.).\n * @returns DataRequest with accountsWithSupportedChains and chainIds.\n */\n #buildDataRequest(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n partial: Partial<\n Omit<DataRequest, 'accountsWithSupportedChains' | 'chainIds'>\n > = {},\n ): DataRequest {\n const chainIdSet = new Set(chainIds);\n const accountsWithSupportedChains: AccountWithSupportedChains[] =\n accounts.map((account) => ({\n account,\n supportedChains: this.#getEnabledChainsForAccount(account).filter(\n (chain) => chainIdSet.has(chain),\n ),\n }));\n return {\n accountsWithSupportedChains,\n chainIds,\n ...partial,\n } as DataRequest;\n }\n\n /**\n * Get the chains that an account supports based on its scopes.\n * Returns the intersection of the account's scopes and the enabled chains.\n *\n * @param account - The account to get supported chains for.\n * @returns Array of ChainIds that the account supports and are enabled.\n */\n #getEnabledChainsForAccount(account: InternalAccount): ChainId[] {\n // Account scopes are CAIP-2 chain IDs like \"eip155:1\", \"solana:mainnet\", \"bip122:...\"\n const scopes = account.scopes ?? [];\n const result: ChainId[] = [];\n\n for (const scope of scopes) {\n const [namespace, reference] = (scope as string).split(':');\n\n // Wildcard scope (e.g., \"eip155:0\" means all enabled chains in that namespace)\n if (reference === '0') {\n for (const chain of this.#enabledChains) {\n if (chain.startsWith(`${namespace}:`)) {\n result.push(chain);\n }\n }\n } else if (namespace === 'eip155' && reference?.startsWith('0x')) {\n // Normalize hex to decimal for EIP155\n result.push(`eip155:${parseInt(reference, 16)}` as ChainId);\n } else {\n result.push(scope);\n }\n }\n\n return result;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n async #handleAccountGroupChanged(): Promise<void> {\n const accounts = this.#selectedAccounts;\n\n log('Account group changed', {\n accountCount: accounts.length,\n accountIds: accounts.map((a) => a.id),\n });\n\n // Subscribe and fetch for the new account group\n this.#subscribeAssets();\n if (accounts.length > 0) {\n await this.getAssets(accounts, {\n chainIds: [...this.#enabledChains],\n forceUpdate: true,\n });\n }\n }\n\n async #handleEnabledNetworksChanged(\n enabledNetworkMap: NetworkEnablementControllerState['enabledNetworkMap'],\n ): Promise<void> {\n const previousChains = this.#enabledChains;\n this.#enabledChains = this.#extractEnabledChains(enabledNetworkMap);\n\n // Find newly enabled chains (in new set but not in previous)\n const addedChains: ChainId[] = [];\n for (const chain of this.#enabledChains) {\n if (!previousChains.has(chain)) {\n addedChains.push(chain);\n }\n }\n\n // Find disabled chains to clean up (in previous but not in new)\n const removedChains: ChainId[] = [];\n for (const chain of previousChains) {\n if (!this.#enabledChains.has(chain)) {\n removedChains.push(chain);\n }\n }\n\n log('Enabled networks changed', {\n previousCount: previousChains.size,\n newCount: this.#enabledChains.size,\n addedChains,\n removedChains,\n });\n\n // Note: We intentionally do NOT delete balance data for disabled chains.\n // Users may want to see historical balances even if the network is currently disabled.\n // The data will simply not be updated until the network is re-enabled.\n\n // Refresh subscriptions for new chain set\n this.#subscribeAssets();\n\n // Do one-time fetch for newly enabled chains\n if (addedChains.length > 0 && this.#selectedAccounts.length > 0) {\n await this.getAssets(this.#selectedAccounts, {\n chainIds: addedChains,\n forceUpdate: true,\n });\n }\n }\n\n /**\n * Handle assets updated from a data source.\n * Called via the onAssetsUpdate callback passed in SubscriptionRequest when the controller subscribes to a data source.\n * Enriches the response with token metadata (via middlewares) before updating state.\n *\n * @param response - The data response with updated assets\n * @param sourceId - The data source ID reporting the update\n * @param request - Optional original request for context when enriching\n */\n async handleAssetsUpdate(\n response: DataResponse,\n sourceId: string,\n request?: DataRequest,\n ): Promise<void> {\n log('Assets updated from data source', {\n sourceId,\n hasBalance: Boolean(response.assetsBalance),\n hasPrice: Boolean(response.assetsPrice),\n });\n\n // Run through enrichment middlewares (Event Stack: Detection → Token → Price)\n // Include 'metadata' in dataTypes so TokenDataSource runs to enrich detected assets\n const enrichedResponse = await this.#executeMiddlewares(\n [\n this.#detectionMiddleware.assetsMiddleware,\n this.#tokenDataSource.assetsMiddleware,\n this.#priceDataSource.assetsMiddleware,\n ],\n request ?? {\n accountsWithSupportedChains: [],\n chainIds: [],\n dataTypes: ['balance', 'metadata', 'price'],\n },\n response,\n );\n\n await this.#updateState(enrichedResponse);\n }\n\n // ============================================================================\n // CLEANUP\n // ============================================================================\n\n destroy(): void {\n log('Destroying AssetsController', {\n dataSourceCount: this.#subscriptionBalanceDataSources.length,\n subscriptionCount: this.#activeSubscriptions.size,\n });\n\n // Destroy instantiated data sources\n this.#backendWebsocketDataSource?.destroy?.();\n this.#accountsApiDataSource?.destroy?.();\n this.#snapDataSource?.destroy?.();\n if (\n this.#rpcDataSource &&\n 'destroy' in this.#rpcDataSource &&\n typeof (this.#rpcDataSource as { destroy: () => void }).destroy ===\n 'function'\n ) {\n (this.#rpcDataSource as { destroy: () => void }).destroy();\n }\n\n // Stop all active subscriptions\n this.#stop();\n\n // Unregister action handlers\n this.messenger.unregisterActionHandler('AssetsController:getAssets');\n this.messenger.unregisterActionHandler('AssetsController:getAssetsBalance');\n this.messenger.unregisterActionHandler('AssetsController:getAssetMetadata');\n this.messenger.unregisterActionHandler('AssetsController:getAssetsPrice');\n this.messenger.unregisterActionHandler('AssetsController:addCustomAsset');\n this.messenger.unregisterActionHandler(\n 'AssetsController:removeCustomAsset',\n );\n this.messenger.unregisterActionHandler('AssetsController:getCustomAssets');\n this.messenger.unregisterActionHandler('AssetsController:hideAsset');\n this.messenger.unregisterActionHandler('AssetsController:unhideAsset');\n }\n}\n"]}
1
+ {"version":3,"file":"AssetsController.mjs","sourceRoot":"","sources":["../src/AssetsController.ts"],"names":[],"mappings":";;;;;;;;;;;;AAIA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAsB3D,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AACrD,OAAO,EAAE,KAAK,EAAE,oBAAoB;AACpC,OAAO,WAAW,qBAAqB;;;AASvC,OAAO,EAAE,qBAAqB,EAAE,iDAA6C;AAC7E,OAAO,EAAE,0BAA0B,EAAE,sDAAkD;AACvF,OAAO,EAAE,eAAe,EAAE,2CAAuC;AAEjE,OAAO,EAAE,aAAa,EAAE,yCAAqC;AAC7D,OAAO,EAAE,cAAc,EAAE,0CAAsC;AAC/D,OAAO,EAAE,eAAe,EAAE,2CAAuC;AACjE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,qBAAiB;AAC7D,OAAO,EAAE,mBAAmB,EAAE,8CAA0C;AAoBxE,OAAO,EAAE,gBAAgB,EAAE,oBAAgB;AAE3C,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E,MAAM,eAAe,GAAG,kBAA2B,CAAC;AAEpD,mFAAmF;AACnF,MAAM,yBAAyB,GAAG;IAChC,WAAW;IACX,kBAAkB;IAClB,kBAAkB;IAClB,gBAAgB;IAChB,gBAAgB;IAChB,mBAAmB;IACnB,iBAAiB;IACjB,WAAW;IACX,aAAa;CACL,CAAC;AAEX,kEAAkE;AAClE,MAAM,2BAA2B,GAAG,KAAM,CAAC;AAE3C,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AA2B/D;;;;GAIG;AACH,MAAM,UAAU,+BAA+B;IAC7C,OAAO;QACL,cAAc,EAAE,EAAE;QAClB,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,EAAE;QAChB,gBAAgB,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC;AAuFD,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,MAAM,aAAa,GAAyC;IAC1D,cAAc,EAAE;QACd,OAAO,EAAE,IAAI;QACb,kBAAkB,EAAE,KAAK;QACzB,sBAAsB,EAAE,KAAK;QAC7B,QAAQ,EAAE,IAAI;KACf;IACD,aAAa,EAAE;QACb,OAAO,EAAE,IAAI;QACb,kBAAkB,EAAE,KAAK;QACzB,sBAAsB,EAAE,KAAK;QAC7B,QAAQ,EAAE,IAAI;KACf;IACD,WAAW,EAAE;QACX,OAAO,EAAE,KAAK;QACd,kBAAkB,EAAE,KAAK;QACzB,sBAAsB,EAAE,KAAK;QAC7B,QAAQ,EAAE,IAAI;KACf;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,IAAI;QACb,kBAAkB,EAAE,KAAK;QACzB,sBAAsB,EAAE,KAAK;QAC7B,QAAQ,EAAE,IAAI;KACf;IACD,gBAAgB,EAAE;QAChB,OAAO,EAAE,IAAI;QACb,kBAAkB,EAAE,KAAK;QACzB,sBAAsB,EAAE,KAAK;QAC7B,QAAQ,EAAE,IAAI;KACf;CACF,CAAC;AAEF,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,SAAS,cAAc,CAAC,OAAsB;IAC5C,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,iBAAiB,CAAC,QAAsB;IAC/C,MAAM,UAAU,GAAiB,EAAE,CAAC;IAEpC,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,UAAU,CAAC,cAAc,GAAG,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1E,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAwB,CAAC,CAAC;YAChE,UAAU,CAAC,cAAc,CAAC,YAAY,CAAC,GAAG,QAAQ,CAAC;QACrD,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QACzB,UAAU,CAAC,WAAW,GAAG,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACpE,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAwB,CAAC,CAAC;YAChE,UAAU,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3B,UAAU,CAAC,aAAa,GAAG,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAChD,QAAQ,CAAC,aAAa,CACvB,EAAE,CAAC;YACF,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;YACzC,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC1D,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAwB,CAAC,CAAC;gBAChE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;IAED,oDAAoD;IACpD,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,UAAU,CAAC,cAAc,GAAG,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAChD,QAAQ,CAAC,cAAc,CACxB,EAAE,CAAC;YACF,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAC9D,gBAAgB,CAAC,OAAO,CAAC,CAC1B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,UAAU,CAAC,MAAM,GAAG,EAAE,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC7C,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,+EAA+E;AAC/E,4BAA4B;AAC5B,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,gBAAiB,SAAQ,cAIrC;IAkEC,YAAY,EACV,SAAS,EACT,KAAK,GAAG,EAAE,EACV,qBAAqB,GAAG,2BAA2B,EACnD,SAAS,GAAG,GAAY,EAAE,CAAC,IAAI,EAC/B,cAAc,EACd,mBAAmB,GACK;QACxB,KAAK,CAAC;YACJ,IAAI,EAAE,eAAe;YACrB,SAAS;YACT,QAAQ,EAAE,aAAa;YACvB,KAAK,EAAE;gBACL,GAAG,+BAA+B,EAAE;gBACpC,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QAjFL,wCAAwC;QAC/B,8CAAoB;QAE7B,0DAA0D;QACjD,0DAA+B;QAE/B,4CAAmB,IAAI,KAAK,EAAE,EAAC;QAExC;;;;;WAKG;QACM,gDAA0D,IAAI,GAAG,EAAE,EAAC;QAE7E,gEAAgE;QAChE,0CAA+B,IAAI,GAAG,EAAE,EAAC;QAehC,+DAAwD;QAExD,0DAA8C;QAE9C,mDAAgC;QAEhC,kDAA8B;QAqB9B,oDAAkC;QAElC,wDAA0C;QAE1C,oDAAkC;QAoBzC,uBAAA,IAAI,+BAAc,SAAS,EAAE,MAAA,CAAC;QAC9B,uBAAA,IAAI,2CAA0B,qBAAqB,MAAA,CAAC;QACpD,MAAM,SAAS,GAAG,mBAAmB,IAAI,EAAE,CAAC;QAE5C,MAAM,qBAAqB,GAAG,CAC5B,cAAsB,EACtB,MAAiB,EACjB,cAAyB,EACnB,EAAE,CACR,IAAI,CAAC,wBAAwB,CAAC,cAAc,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;QAExE,uBAAA,IAAI,gDAA+B,IAAI,0BAA0B,CAAC;YAChE,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,cAAc;YACd,qBAAqB;SACtB,CAAC,MAAA,CAAC;QACH,uBAAA,IAAI,2CAA0B,IAAI,qBAAqB,CAAC;YACtD,cAAc;YACd,qBAAqB;SACtB,CAAC,MAAA,CAAC;QACH,uBAAA,IAAI,oCAAmB,IAAI,cAAc,CAAC;YACxC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,qBAAqB;SACtB,CAAC,MAAA,CAAC;QACH,uBAAA,IAAI,mCAAkB,IAAI,aAAa,CAAC;YACtC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,qBAAqB;YACrB,GAAG,SAAS;SACb,CAAC,MAAA,CAAC;QACH,uBAAA,IAAI,qCAAoB,IAAI,eAAe,CAAC;YAC1C,cAAc;SACf,CAAC,MAAA,CAAC;QACH,uBAAA,IAAI,qCAAoB,IAAI,eAAe,CAAC;YAC1C,cAAc;SACf,CAAC,MAAA,CAAC;QACH,uBAAA,IAAI,yCAAwB,IAAI,mBAAmB,EAAE,MAAA,CAAC;QAEtD,IAAI,CAAC,uBAAA,IAAI,mCAAW,EAAE,CAAC;YACrB,GAAG,CAAC,uDAAuD,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,GAAG,CAAC,+BAA+B,EAAE;YACnC,qBAAqB,EAAE,uBAAA,IAAI,+CAAuB;SACnD,CAAC,CAAC;QAEH,uBAAA,IAAI,sEAAiB,MAArB,IAAI,CAAmB,CAAC;QACxB,uBAAA,IAAI,wEAAmB,MAAvB,IAAI,CAAqB,CAAC;QAC1B,uBAAA,IAAI,6EAAwB,MAA5B,IAAI,CAA0B,CAAC;IACjC,CAAC;IAqGD,+EAA+E;IAC/E,+BAA+B;IAC/B,+EAA+E;IAE/E;;;;;;;;;;;;OAYG;IACH,wBAAwB,CACtB,YAAoB,EACpB,YAAuB,EACvB,cAAyB;QAEzB,GAAG,CAAC,mCAAmC,EAAE;YACvC,YAAY;YACZ,UAAU,EAAE,YAAY,CAAC,MAAM;YAC/B,MAAM,EAAE,YAAY;SACrB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAc,cAAc,CAAC;QAE3C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACtE,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QAE1E,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,gEAAgE;YAChE,uBAAA,IAAI,sEAAiB,MAArB,IAAI,CAAmB,CAAC;QAC1B,CAAC;QAED,wEAAwE;QACxE,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,uBAAA,IAAI,2EAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,MAAM,kBAAkB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CACtD,uBAAA,IAAI,uCAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAC/B,CAAC;YACF,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,GAAG,CAAC,0CAA0C,EAAE,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBACxE,IAAI,CAAC,SAAS,CAAC,uBAAA,IAAI,2EAAkB,EAAE;oBACrC,QAAQ,EAAE,kBAAkB;oBAC5B,WAAW,EAAE,IAAI;iBAClB,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;oBACjB,GAAG,CAAC,0CAA0C,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC7D,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IA8CD,+EAA+E;IAC/E,4BAA4B;IAC5B,+EAA+E;IAE/E,KAAK,CAAC,SAAS,CACb,QAA2B,EAC3B,OAKC;QAED,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,CAAC,GAAG,uBAAA,IAAI,uCAAe,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAEzE,mDAAmD;QACnD,MAAM,YAAY,GAAoB,EAAE,CAAC;QACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,mBAAmB,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC7D,YAAY,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,OAAO,EAAE,WAAW,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,uBAAA,IAAI,uEAAkB,MAAtB,IAAI,EAAmB,QAAQ,EAAE,QAAQ,EAAE;gBACzD,UAAU;gBACV,SAAS;gBACT,YAAY,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;gBAChE,WAAW,EAAE,IAAI;aAClB,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,uBAAA,IAAI,yEAAoB,MAAxB,IAAI,EACzB;gBACE,uBAAA,IAAI,+CAAuB,CAAC,gBAAgB;gBAC5C,uBAAA,IAAI,wCAAgB,CAAC,gBAAgB;gBACrC,uBAAA,IAAI,uCAAe,CAAC,gBAAgB;gBACpC,uBAAA,IAAI,6CAAqB,CAAC,gBAAgB;gBAC1C,uBAAA,IAAI,yCAAiB,CAAC,gBAAgB;gBACtC,uBAAA,IAAI,yCAAiB,CAAC,gBAAgB;aACvC,EACD,OAAO,CACR,CAAC;YACF,MAAM,uBAAA,IAAI,kEAAa,MAAjB,IAAI,EAAc,QAAQ,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,uBAAA,IAAI,yEAAoB,MAAxB,IAAI,EAAqB,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,QAA2B,EAC3B,OAIC;QAED,mDAAmD;QACnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;YAC5C,QAAQ,EAAE,OAAO,EAAE,QAAQ;YAC3B,UAAU,EAAE,OAAO,EAAE,UAAU;YAC/B,WAAW,EAAE,OAAO,EAAE,WAAW;YACjC,SAAS,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;SACnC,CAAC,CAAC;QAEH,2CAA2C;QAC3C,MAAM,MAAM,GAA2D,EAAE,CAAC;QAC1E,KAAK,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAChE,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC7D,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBAClB,MAAM,CAAC,SAAS,CAAC,CAAC,OAAwB,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;gBAC9D,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,gBAAgB,CAAC,OAAsB;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAA8B,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,QAA2B,EAC3B,OAIC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;YAC5C,QAAQ,EAAE,OAAO,EAAE,QAAQ;YAC3B,UAAU,EAAE,OAAO,EAAE,UAAU;YAC/B,WAAW,EAAE,OAAO,EAAE,WAAW;YACjC,SAAS,EAAE,CAAC,OAAO,CAAC;SACrB,CAAC,CAAC;QAEH,qEAAqE;QACrE,MAAM,MAAM,GAAsC,EAAE,CAAC;QACrD,KAAK,MAAM,aAAa,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC7D,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAChB,MAAM,CAAC,OAAwB,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+EAA+E;IAC/E,2BAA2B;IAC3B,+EAA+E;IAE/E;;;;;;;OAOG;IACH,KAAK,CAAC,cAAc,CAClB,SAAoB,EACpB,OAAsB;QAEtB,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAEpD,GAAG,CAAC,qBAAqB,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAEtE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,YAAY,GAAG,KAAK,CAAC,YAAwC,CAAC;YACpE,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,YAAY,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;YAC/B,CAAC;YAED,kCAAkC;YAClC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACzD,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAClD,CAAC;YAED,2DAA2D;YAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;YACxD,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;gBAClB,OAAO,KAAK,CAAC,MAAM,CAAC;gBACpB,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACpC,OAAO,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,8CAA8C;QAC9C,MAAM,OAAO,GAAG,uBAAA,IAAI,2EAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QACvE,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;YAClD,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE;gBAC9B,QAAQ,EAAE,CAAC,OAAO,CAAC;gBACnB,WAAW,EAAE,IAAI;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,SAAoB,EAAE,OAAsB;QAC5D,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAEpD,GAAG,CAAC,uBAAuB,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,IAAI,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;gBAClC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAClE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,iBAAiB,CACjC,CAAC;gBAEF,wBAAwB;gBACxB,IAAI,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC/C,OAAO,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAC,SAAoB;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAClD,CAAC;IAED,+EAA+E;IAC/E,2BAA2B;IAC3B,+EAA+E;IAE/E;;;;;;OAMG;IACH,SAAS,CAAC,OAAsB;QAC9B,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAEpD,GAAG,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAEpD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBAC/C,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC;YACjD,CAAC;YACD,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,OAAsB;QAChC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAEpD,GAAG,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAEtD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;YACxD,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC,MAAM,CAAC;gBACpB,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACpC,OAAO,KAAK,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,+EAA+E;IAC/E,gBAAgB;IAChB,+EAA+E;IAE/E;;;;;;;;OAQG;IACH,oBAAoB,CAClB,QAA2B,EAC3B,QAAmB,EACnB,UAAuC,EAAE;QAEzC,MAAM,EAAE,cAAc,GAAG,uBAAA,IAAI,+CAAuB,EAAE,GAAG,OAAO,CAAC;QACjE,MAAM,eAAe,GAAG,oBAAoB,CAAC;QAE7C,MAAM,oBAAoB,GAAG,uBAAA,IAAI,6CAAqB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,oBAAoB,KAAK,SAAS,CAAC;QAEpD,MAAM,YAAY,GAAwB;YACxC,OAAO,EAAE,uBAAA,IAAI,uEAAkB,MAAtB,IAAI,EAAmB,QAAQ,EAAE,QAAQ,EAAE;gBAClD,SAAS,EAAE,CAAC,OAAO,CAAC;gBACpB,cAAc;aACf,CAAC;YACF,cAAc,EAAE,eAAe;YAC/B,QAAQ;YACR,cAAc,EAAE,CAAC,QAAQ,EAAE,EAAE,CAC3B,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,CAAC;YACtD,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;SACjC,CAAC;QAEF,uBAAA,IAAI,yCAAiB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAEnE,qBAAqB;QACrB,MAAM,YAAY,GAAyB;YACzC,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,eAAe;YAC1B,UAAU,EAAE,CAAC,UAAU,CAAC;YACxB,SAAS,EAAE,CAAC,OAAO,CAAC;YACpB,WAAW,EAAE,GAAG,EAAE;gBAChB,uBAAA,IAAI,6CAAqB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YACpD,CAAC;SACF,CAAC;QAEF,uBAAA,IAAI,6CAAqB,CAAC,GAAG,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACH,sBAAsB;QACpB,MAAM,eAAe,GAAG,oBAAoB,CAAC;QAC7C,MAAM,oBAAoB,GAAG,uBAAA,IAAI,6CAAqB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAE5E,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,uBAAA,IAAI,yCAAiB,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxE,oBAAoB,CAAC,WAAW,EAAE,CAAC;IACrC,CAAC;IA6nBD;;;;;;;;OAQG;IACH,KAAK,CAAC,kBAAkB,CACtB,QAAsB,EACtB,QAAgB,EAChB,OAAqB;QAErB,GAAG,CAAC,iCAAiC,EAAE;YACrC,QAAQ;YACR,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;YAC3C,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;SACxC,CAAC,CAAC;QAEH,8EAA8E;QAC9E,oFAAoF;QACpF,MAAM,gBAAgB,GAAG,MAAM,uBAAA,IAAI,yEAAoB,MAAxB,IAAI,EACjC;YACE,uBAAA,IAAI,6CAAqB,CAAC,gBAAgB;YAC1C,uBAAA,IAAI,yCAAiB,CAAC,gBAAgB;YACtC,uBAAA,IAAI,yCAAiB,CAAC,gBAAgB;SACvC,EACD,OAAO,IAAI;YACT,2BAA2B,EAAE,EAAE;YAC/B,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC;SAC5C,EACD,QAAQ,CACT,CAAC;QAEF,MAAM,uBAAA,IAAI,kEAAa,MAAjB,IAAI,EAAc,gBAAgB,CAAC,CAAC;IAC5C,CAAC;IAED,+EAA+E;IAC/E,UAAU;IACV,+EAA+E;IAE/E,OAAO;QACL,GAAG,CAAC,6BAA6B,EAAE;YACjC,eAAe,EAAE,uBAAA,IAAI,yFAAgC,CAAC,MAAM;YAC5D,iBAAiB,EAAE,uBAAA,IAAI,6CAAqB,CAAC,IAAI;SAClD,CAAC,CAAC;QAEH,oCAAoC;QACpC,uBAAA,IAAI,oDAA4B,EAAE,OAAO,EAAE,EAAE,CAAC;QAC9C,uBAAA,IAAI,+CAAuB,EAAE,OAAO,EAAE,EAAE,CAAC;QACzC,uBAAA,IAAI,wCAAgB,EAAE,OAAO,EAAE,EAAE,CAAC;QAClC,IACE,uBAAA,IAAI,uCAAe;YACnB,SAAS,IAAI,uBAAA,IAAI,uCAAe;YAChC,OAAQ,uBAAA,IAAI,uCAA2C,CAAC,OAAO;gBAC7D,UAAU,EACZ,CAAC;YACA,uBAAA,IAAI,uCAA2C,CAAC,OAAO,EAAE,CAAC;QAC7D,CAAC;QAED,gCAAgC;QAChC,uBAAA,IAAI,2DAAM,MAAV,IAAI,CAAQ,CAAC;QAEb,6BAA6B;QAC7B,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,4BAA4B,CAAC,CAAC;QACrE,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,mCAAmC,CAAC,CAAC;QAC5E,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,mCAAmC,CAAC,CAAC;QAC5E,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,iCAAiC,CAAC,CAAC;QAC1E,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,iCAAiC,CAAC,CAAC;QAC1E,IAAI,CAAC,SAAS,CAAC,uBAAuB,CACpC,oCAAoC,CACrC,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,kCAAkC,CAAC,CAAC;QAC3E,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,4BAA4B,CAAC,CAAC;QACrE,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,8BAA8B,CAAC,CAAC;IACzE,CAAC;CACF;;IA/yCG,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CACxB,2DAA2D,CAC5D,CAAC;AACJ,CAAC;IAqBC,OAAO;QACL,uBAAA,IAAI,oDAA4B;QAChC,uBAAA,IAAI,+CAAuB;QAC3B,uBAAA,IAAI,wCAAgB;QACpB,uBAAA,IAAI,uCAAe;KACpB,CAAC;AACJ,CAAC;IAkFC,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAC/C,sCAAsC,CACvC,CAAC;IACF,uBAAA,IAAI,mCAAkB,uBAAA,IAAI,2EAAsB,MAA1B,IAAI,EAAuB,iBAAiB,CAAC,MAAA,CAAC;IAEpE,GAAG,CAAC,mBAAmB,EAAE;QACvB,iBAAiB;QACjB,aAAa,EAAE,uBAAA,IAAI,uCAAe;KACnC,CAAC,CAAC;AACL,CAAC,2FAaC,iBAAwE;IAExE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAW,CAAC;IAElC,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACtE,KAAK,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9D,IAAI,SAAS,EAAE,CAAC;gBACd,wEAAwE;gBACxE,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC5B,qCAAqC;oBACrC,MAAM,CAAC,GAAG,CAAC,SAAoB,CAAC,CAAC;gBACnC,CAAC;qBAAM,CAAC;oBACN,0EAA0E;oBAC1E,MAAM,mBAAmB,GAAG,uBAAA,IAAI,8EAAyB,MAA7B,IAAI,EAC9B,SAAS,EACT,SAAS,CACV,CAAC;oBACF,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,IAAI,mBAAmB,EAAE,CAAC,CAAC;gBACpD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,iGAUwB,SAAiB,EAAE,SAAiB;IAC3D,IAAI,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzD,2CAA2C;QAC3C,OAAO,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5C,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;IAGC,6GAA6G;IAC7G,IAAI,CAAC,SAAS,CAAC,SAAS,CACtB,kDAAkD,EAClD,GAAG,EAAE;QACH,uBAAA,IAAI,gFAA2B,MAA/B,IAAI,CAA6B,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC,CACF,CAAC;IAEF,mEAAmE;IACnE,IAAI,CAAC,SAAS,CAAC,SAAS,CACtB,yCAAyC,EACzC,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE;QACxB,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,EAA+B,iBAAiB,CAAC,CAAC,KAAK,CACzD,OAAO,CAAC,KAAK,CACd,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,2DAA2D;IAC3D,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,uBAAA,IAAI,4DAAO,MAAX,IAAI,CAAS,CAAC,CAAC;IAC1E,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,uBAAA,IAAI,2DAAM,MAAV,IAAI,CAAQ,CAAC,CAAC;AACzE,CAAC;IAGC,IAAI,CAAC,SAAS,CAAC,4BAA4B,CACzC,IAAI,EACJ,yBAAyB,CAC1B,CAAC;AACJ,CAAC;AA0DD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;;;GAOG;AACH,KAAK,+CACH,WAAyB,EACzB,OAAoB,EACpB,kBAAgC,EAAE;IAElC,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CACnC,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CACnB,KAAK,EACH,GAAG,EAKF,EAAE;QACH,IAAI,CAAC;YACH,OAAO,MAAM,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,EACH,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CACnB,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC;QACzB,OAAO;QACP,QAAQ,EAAE,eAAe;QACzB,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAsC;KAClE,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,QAAQ,CAAC;AACzB,CAAC;AAsTD,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,KAAK,wCAAc,QAAsB;IACvC,uEAAuE;IACvE,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAEvD,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,yCAAiB,CAAC,OAAO,EAAE,CAAC;IAE1D,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC;QACjC,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACrD,6DAA6D;QAC7D,MAAM,cAAc,GAClB,kBAAkB,CAAC,cAAc,IAAI,EAAE,CAAC;QAE1C,mCAAmC;QACnC,MAAM,eAAe,GAKf,EAAE,CAAC;QACT,MAAM,eAAe,GAAa,EAAE,CAAC;QAErC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,qFAAqF;YACrF,MAAM,QAAQ,GAAG,KAAK,CAAC,cAA+C,CAAC;YACvE,MAAM,QAAQ,GAAG,KAAK,CAAC,aAGtB,CAAC;YACF,MAAM,MAAM,GAAG,KAAK,CAAC,WAAyC,CAAC;YAE/D,IAAI,kBAAkB,CAAC,cAAc,EAAE,CAAC;gBACtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CACvC,kBAAkB,CAAC,cAAc,CAClC,EAAE,CAAC;oBACF,IACE,CAAC,OAAO,CACN,aAAa,CAAC,cAAc,CAAC,GAAoB,CAAC,EAClD,KAAK,CACN,EACD,CAAC;wBACD,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBAC5B,CAAC;oBACD,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACxB,CAAC;YACH,CAAC;YAED,IAAI,kBAAkB,CAAC,aAAa,EAAE,CAAC;gBACrC,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CACvD,kBAAkB,CAAC,aAAa,CACjC,EAAE,CAAC;oBACF,MAAM,gBAAgB,GACpB,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;oBAE/C,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;wBACzB,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;oBAC3B,CAAC;oBAED,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;wBACjE,MAAM,eAAe,GAAG,gBAAgB,CACtC,OAAwB,CACS,CAAC;wBACpC,MAAM,WAAW,GAAG,OAA6B,CAAC;wBAClD,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC;wBACrC,MAAM,SAAS,GAAG,eAAe,EAAE,MAAM,CAAC;wBAE1C,oCAAoC;wBACpC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;4BAC5B,eAAe,CAAC,IAAI,CAAC;gCACnB,SAAS;gCACT,OAAO;gCACP,SAAS;gCACT,SAAS;6BACV,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;oBAED,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YAED,yBAAyB;YACzB,IAAI,kBAAkB,CAAC,WAAW,EAAE,CAAC;gBACnC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CACvC,kBAAkB,CAAC,WAAW,CAC/B,EAAE,CAAC;oBACF,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,2BAA2B;QAC3B,MAAM,kBAAkB,GAAa,kBAAkB,CAAC,WAAW;YACjE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,MAAM,CAChD,CAAC,OAAO,EAAE,EAAE,CACV,CAAC,OAAO,CACN,cAAc,CAAC,OAAwB,CAAC,EACxC,kBAAkB,CAAC,WAAW,EAAE,CAAC,OAAwB,CAAC,CAC3D,CACJ;YACH,CAAC,CAAC,EAAE,CAAC;QAEP,0BAA0B;QAC1B,IACE,eAAe,CAAC,MAAM,GAAG,CAAC;YAC1B,eAAe,CAAC,MAAM,GAAG,CAAC;YAC1B,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAC7B,CAAC;YACD,GAAG,CAAC,eAAe,EAAE;gBACnB,eAAe,EACb,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;gBAC1D,oBAAoB,EAClB,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBACjE,kBAAkB,EAChB,kBAAkB,CAAC,MAAM,GAAG,CAAC;oBAC3B,CAAC,CAAC,kBAAkB,CAAC,MAAM;oBAC3B,CAAC,CAAC,SAAS;gBACf,SAAS,EACP,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC;oBACpC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC3D,SAAS;wBACT,MAAM;qBACP,CAAC,CAAC;oBACL,CAAC,CAAC,SAAS;aAChB,CAAC,CAAC;QACL,CAAC;QAED,iCAAiC;QACjC,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;YACrC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,iCAAiC,EAAE;gBACxD,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,OAAO,EAAE,MAAM,CAAC,OAAwB;gBACxC,cAAc,EAAE,MAAM,CAAC,SAAS,IAAI,GAAG;gBACvC,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAC,CAAC;QACL,CAAC;QAED,mDAAmD;QACnD,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,kBAAkB,CAAC,WAAW,EAAE,CAAC;YACpE,+CAA+C;YAC/C,MAAM,aAAa,GAAsC,EAAE,CAAC;YAC5D,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;gBACzC,MAAM,KAAK,GACT,kBAAkB,CAAC,WAAW,CAAC,OAAwB,CAAC,CAAC;gBAC3D,IAAI,KAAK,EAAE,CAAC;oBACV,aAAa,CAAC,OAAwB,CAAC,GAAG,KAAK,CAAC;gBAClD,CAAC;YACH,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,+BAA+B,EAAE;gBACtD,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;QACL,CAAC;QAED,iCAAiC;QACjC,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YACnE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,iCAAiC,EAAE;oBACxD,SAAS;oBACT,QAAQ;iBACT,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,WAAW,EAAE,CAAC;IAChB,CAAC;AACH,CAAC,uFAGC,QAA2B,EAC3B,QAAmB,EACnB,UAAuB;IAEvB,MAAM,MAAM,GAAoD,EAAE,CAAC;IACnE,mCAAmC;IACnC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAEzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;QAExB,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAEnE,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YACjE,MAAM,YAAY,GAAG,OAAwB,CAAC;YAE9C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;YAE5D,+BAA+B;YAC/B,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,WAAW,CAAC;YAE7B,wCAAwC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;YACxD,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;gBAClB,SAAS;YACX,CAAC;YAED,MAAM,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;YAElD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBAClC,SAAS;YACX,CAAC;YAED,uBAAuB;YACvB,MAAM,cAAc,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,EAA2B,QAAQ,CAAC,IAAI,CAAC,CAAC;YACrE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;gBACtC,SAAS;YACX,CAAC;YAED,MAAM,YAAY,GAAG,OAAO,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YACtD,MAAM,KAAK,GAAe,QAAQ,IAAI;gBACpC,KAAK,EAAE,CAAC;gBACR,WAAW,EAAE,CAAC;aACf,CAAC;YAEF,mDAAmD;YACnD,sFAAsF;YACtF,0CAA0C;YAC1C,MAAM,aAAa,GAAG,IAAI,WAAW,CAAC,YAAY,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;YAClE,MAAM,SAAS,GAAG,aAAa;iBAC5B,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;iBAC9B,QAAQ,EAAE,CAAC;YAEd,MAAM,KAAK,GAAU;gBACnB,EAAE,EAAE,YAAY;gBAChB,OAAO,EAAE,YAAY;gBACrB,OAAO,EAAE,YAAY;gBACrB,QAAQ;gBACR,KAAK;gBACL,SAAS;aACV,CAAC;YAEF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,mGAQyB,aAAqB;IAC7C,QAAQ,aAAa,EAAE,CAAC;QACtB,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO,CAAC;QACb,KAAK,KAAK;YACR,OAAO,UAAU,CAAC;QACpB,KAAK,QAAQ;YACX,OAAO,KAAK,CAAC;QACf,KAAK,SAAS;YACZ,uEAAuE;YACvE,OAAO,aAAa,CAAC;QACvB;YACE,wCAAwC;YACxC,OAAO,UAAU,CAAC;IACtB,CAAC;AACH,CAAC;IAWC,GAAG,CAAC,yBAAyB,EAAE;QAC7B,oBAAoB,EAAE,uBAAA,IAAI,2EAAkB,CAAC,MAAM;QACnD,iBAAiB,EAAE,uBAAA,IAAI,uCAAe,CAAC,IAAI;KAC5C,CAAC,CAAC;IAEH,uBAAA,IAAI,sEAAiB,MAArB,IAAI,CAAmB,CAAC;IACxB,IAAI,uBAAA,IAAI,2EAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,CAAC,uBAAA,IAAI,2EAAkB,EAAE;YACrC,QAAQ,EAAE,CAAC,GAAG,uBAAA,IAAI,uCAAe,CAAC;YAClC,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACjB,GAAG,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;IAOC,GAAG,CAAC,yBAAyB,EAAE;QAC7B,uBAAuB,EAAE,uBAAA,IAAI,6CAAqB,CAAC,IAAI;QACvD,oBAAoB,EAAE,uBAAA,IAAI,6CAAqB,CAAC,GAAG,CAAC,oBAAoB,CAAC;KAC1E,CAAC,CAAC;IAEH,6DAA6D;IAC7D,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAE9B,8EAA8E;IAC9E,sDAAsD;IACtD,iEAAiE;IACjE,MAAM,gBAAgB,GAAG,CAAC,GAAG,uBAAA,IAAI,6CAAqB,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/D,KAAK,MAAM,eAAe,IAAI,gBAAgB,EAAE,CAAC;QAC/C,IAAI,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,uBAAA,IAAI,yFAAgC,CAAC,IAAI,CACtD,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAClC,CAAC;YACF,IAAI,MAAM,EAAE,CAAC;gBACX,uBAAA,IAAI,4EAAuB,MAA3B,IAAI,EAAwB,MAAM,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;IACH,CAAC;IACD,uBAAA,IAAI,6CAAqB,CAAC,KAAK,EAAE,CAAC;AACpC,CAAC;IAMC,IAAI,uBAAA,IAAI,2EAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO;IACT,CAAC;IAED,wDAAwD;IACxD,uBAAA,IAAI,6EAAwB,MAA5B,IAAI,EAAyB,uBAAA,IAAI,2EAAkB,EAAE;QACnD,GAAG,uBAAA,IAAI,uCAAe;KACvB,CAAC,CAAC;IAEH,sEAAsE;IACtE,IAAI,CAAC,oBAAoB,CAAC,uBAAA,IAAI,2EAAkB,EAAE,CAAC,GAAG,uBAAA,IAAI,uCAAe,CAAC,CAAC,CAAC;AAC9E,CAAC,+FAiBC,QAA2B,EAC3B,QAAmB;IAEnB,MAAM,eAAe,GAAG,uBAAA,IAAI,8EAAyB,MAA7B,IAAI,EAC1B,QAAQ,EACR,IAAI,GAAG,CAAC,QAAQ,CAAC,CAClB,CAAC;IACF,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC;IAExD,KAAK,MAAM,MAAM,IAAI,uBAAA,IAAI,yFAAgC,EAAE,CAAC;QAC1D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC,CAAC;QAC9D,MAAM,cAAc,GAAc,EAAE,CAAC;QAErC,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;YACtC,IAAI,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC7B,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,uBAAA,IAAI,4EAAuB,MAA3B,IAAI,EAAwB,MAAM,CAAC,CAAC;YACpC,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,MAAM,iBAAiB,GAAG,cAAc;aACrC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;aACxD,MAAM,CACL,CAAC,OAAO,EAAE,EAAE,CACV,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAC9D,CAAC;QACJ,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,uBAAA,IAAI,0EAAqB,MAAzB,IAAI,EAAsB,MAAM,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC,iGAWC,QAA2B,EAC3B,iBAA+B;IAE/B,MAAM,eAAe,GAAG,IAAI,GAAG,EAA8B,CAAC;IAC9D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,OAAO,IAAI,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,EAA6B,OAAO,CAAC,EAAE,CAAC;YAChE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpC,SAAS;YACX,CAAC;YACD,IAAI,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACxC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,GAAG,EAAE,CAAC;gBACV,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACrC,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC,yFAWC,MAAmD,EACnD,QAA2B,EAC3B,MAAiB;IAEjB,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IAClC,MAAM,eAAe,GAAG,MAAM,QAAQ,EAAE,CAAC;IACzC,MAAM,oBAAoB,GAAG,uBAAA,IAAI,6CAAqB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,oBAAoB,KAAK,SAAS,CAAC;IAEpD,GAAG,CAAC,0BAA0B,EAAE;QAC9B,QAAQ;QACR,eAAe;QACf,QAAQ;QACR,YAAY,EAAE,QAAQ,CAAC,MAAM;QAC7B,UAAU,EAAE,MAAM,CAAC,MAAM;KAC1B,CAAC,CAAC;IAEH,MAAM,YAAY,GAAwB;QACxC,OAAO,EAAE,uBAAA,IAAI,uEAAkB,MAAtB,IAAI,EAAmB,QAAQ,EAAE,MAAM,EAAE;YAChD,UAAU,EAAE,CAAC,UAAU,CAAC;YACxB,SAAS,EAAE,CAAC,SAAS,CAAC;YACtB,cAAc,EAAE,uBAAA,IAAI,+CAAuB;SAC5C,CAAC;QACF,cAAc,EAAE,eAAe;QAC/B,QAAQ;QACR,cAAc,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACzE,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;KACjC,CAAC;IAEF,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QAC7C,OAAO,CAAC,KAAK,CACX,8CAA8C,QAAQ,IAAI,EAC1D,KAAK,CACN,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,qBAAqB;IACrB,MAAM,YAAY,GAAyB;QACzC,MAAM;QACN,SAAS,EAAE,eAAe;QAC1B,UAAU,EAAE,CAAC,UAAU,CAAC;QACxB,SAAS,EAAE,CAAC,SAAS,CAAC;QACtB,WAAW,EAAE,GAAG,EAAE;YAChB,uBAAA,IAAI,6CAAqB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACpD,CAAC;KACF,CAAC;IAEF,uBAAA,IAAI,6CAAqB,CAAC,GAAG,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;AAC/D,CAAC,6FAQC,MAAmD;IAEnD,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;IACjD,MAAM,oBAAoB,GAAG,uBAAA,IAAI,6CAAqB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAE5E,IAAI,oBAAoB,EAAE,CAAC;QACzB,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC3D,oBAAoB,CAAC,WAAW,EAAE,CAAC;IACrC,CAAC;AACH,CAAC,mFAeC,QAA2B,EAC3B,QAAmB,EACnB,UAEI,EAAE;IAEN,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,2BAA2B,GAC/B,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACzB,OAAO;QACP,eAAe,EAAE,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,EAA6B,OAAO,CAAC,CAAC,MAAM,CAC/D,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CACjC;KACF,CAAC,CAAC,CAAC;IACN,OAAO;QACL,2BAA2B;QAC3B,QAAQ;QACR,GAAG,OAAO;KACI,CAAC;AACnB,CAAC,uGAS2B,OAAwB;IAClD,sFAAsF;IACtF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;IACpC,MAAM,MAAM,GAAc,EAAE,CAAC;IAE7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAI,KAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE5D,+EAA+E;QAC/E,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;YACtB,KAAK,MAAM,KAAK,IAAI,uBAAA,IAAI,uCAAe,EAAE,CAAC;gBACxC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC;oBACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;aAAM,IAAI,SAAS,KAAK,QAAQ,IAAI,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACjE,sCAAsC;YACtC,MAAM,CAAC,IAAI,CAAC,UAAU,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,EAAa,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,KAAK;IACH,MAAM,QAAQ,GAAG,uBAAA,IAAI,2EAAkB,CAAC;IAExC,GAAG,CAAC,uBAAuB,EAAE;QAC3B,YAAY,EAAE,QAAQ,CAAC,MAAM;QAC7B,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC,CAAC;IAEH,gDAAgD;IAChD,uBAAA,IAAI,sEAAiB,MAArB,IAAI,CAAmB,CAAC;IACxB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;YAC7B,QAAQ,EAAE,CAAC,GAAG,uBAAA,IAAI,uCAAe,CAAC;YAClC,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC;AACH,CAAC,mDAED,KAAK,yDACH,iBAAwE;IAExE,MAAM,cAAc,GAAG,uBAAA,IAAI,uCAAe,CAAC;IAC3C,uBAAA,IAAI,mCAAkB,uBAAA,IAAI,2EAAsB,MAA1B,IAAI,EAAuB,iBAAiB,CAAC,MAAA,CAAC;IAEpE,6DAA6D;IAC7D,MAAM,WAAW,GAAc,EAAE,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,uBAAA,IAAI,uCAAe,EAAE,CAAC;QACxC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,MAAM,aAAa,GAAc,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC,uBAAA,IAAI,uCAAe,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,GAAG,CAAC,0BAA0B,EAAE;QAC9B,aAAa,EAAE,cAAc,CAAC,IAAI;QAClC,QAAQ,EAAE,uBAAA,IAAI,uCAAe,CAAC,IAAI;QAClC,WAAW;QACX,aAAa;KACd,CAAC,CAAC;IAEH,yEAAyE;IACzE,uFAAuF;IACvF,uEAAuE;IAEvE,0CAA0C;IAC1C,uBAAA,IAAI,sEAAiB,MAArB,IAAI,CAAmB,CAAC;IAExB,6CAA6C;IAC7C,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,uBAAA,IAAI,2EAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,CAAC,SAAS,CAAC,uBAAA,IAAI,2EAAkB,EAAE;YAC3C,QAAQ,EAAE,WAAW;YACrB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["import type {\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n} from '@metamask/account-tree-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n ApiPlatformClient,\n BackendWebSocketServiceActions,\n BackendWebSocketServiceEvents,\n} from '@metamask/core-backend';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkEnablementControllerGetStateAction,\n NetworkEnablementControllerEvents,\n NetworkEnablementControllerState,\n} from '@metamask/network-enablement-controller';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BigNumberJS from 'bignumber.js';\nimport { isEqual } from 'lodash';\n\nimport type { AssetsControllerMethodActions } from './AssetsController-method-action-types';\nimport type {\n AbstractDataSource,\n DataSourceState,\n SubscriptionRequest,\n} from './data-sources/AbstractDataSource';\nimport { AccountsApiDataSource } from './data-sources/AccountsApiDataSource';\nimport { BackendWebsocketDataSource } from './data-sources/BackendWebsocketDataSource';\nimport { PriceDataSource } from './data-sources/PriceDataSource';\nimport type { RpcDataSourceConfig } from './data-sources/RpcDataSource';\nimport { RpcDataSource } from './data-sources/RpcDataSource';\nimport { SnapDataSource } from './data-sources/SnapDataSource';\nimport { TokenDataSource } from './data-sources/TokenDataSource';\nimport { projectLogger, createModuleLogger } from './logger';\nimport { DetectionMiddleware } from './middlewares/DetectionMiddleware';\nimport type {\n AccountId,\n AssetPreferences,\n ChainId,\n Caip19AssetId,\n AssetMetadata,\n AssetPrice,\n AssetBalance,\n AccountWithSupportedChains,\n AssetType,\n DataType,\n DataRequest,\n DataResponse,\n NextFunction,\n Middleware,\n SubscriptionResponse,\n Asset,\n AssetsControllerStateInternal,\n} from './types';\nimport { normalizeAssetId } from './utils';\n\n// ============================================================================\n// CONTROLLER CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'AssetsController' as const;\n\n/** Method names exposed as messenger actions (AssetsController:getAssets, etc.) */\nconst MESSENGER_EXPOSED_METHODS = [\n 'getAssets',\n 'getAssetsBalance',\n 'getAssetMetadata',\n 'getAssetsPrice',\n 'addCustomAsset',\n 'removeCustomAsset',\n 'getCustomAssets',\n 'hideAsset',\n 'unhideAsset',\n] as const;\n\n/** Default polling interval hint for data sources (30 seconds) */\nconst DEFAULT_POLLING_INTERVAL_MS = 30_000;\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// STATE TYPES\n// ============================================================================\n\n/**\n * State structure for AssetsController.\n *\n * All values are JSON-serializable. UI preferences (e.g. hidden) are in\n * assetPreferences, not in metadata.\n *\n * @see AssetsControllerStateInternal for the semantic type structure\n */\nexport type AssetsControllerState = {\n /** Shared metadata for all assets (stored once per asset) */\n assetsMetadata: { [assetId: string]: AssetMetadata };\n /** Per-account balance data */\n assetsBalance: { [accountId: string]: { [assetId: string]: AssetBalance } };\n /** Price data for assets */\n assetsPrice: { [assetId: string]: AssetPrice };\n /** Custom assets added by users per account (CAIP-19 asset IDs) */\n customAssets: { [accountId: string]: Caip19AssetId[] };\n /** UI preferences per asset (e.g. hidden) */\n assetPreferences: { [assetId: string]: AssetPreferences };\n};\n\n/**\n * Returns the default state for AssetsController.\n *\n * @returns The default AssetsController state with empty maps.\n */\nexport function getDefaultAssetsControllerState(): AssetsControllerState {\n return {\n assetsMetadata: {},\n assetsBalance: {},\n assetsPrice: {},\n customAssets: {},\n assetPreferences: {},\n };\n}\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\nexport type AssetsControllerGetStateAction = ControllerGetStateAction<\n typeof CONTROLLER_NAME,\n AssetsControllerState\n>;\n\nexport type AssetsControllerActions =\n | AssetsControllerGetStateAction\n | AssetsControllerMethodActions;\n\nexport type AssetsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof CONTROLLER_NAME,\n AssetsControllerState\n>;\n\nexport type AssetsControllerBalanceChangedEvent = {\n type: `${typeof CONTROLLER_NAME}:balanceChanged`;\n payload: [\n {\n accountId: AccountId;\n assetId: Caip19AssetId;\n previousAmount: string;\n newAmount: string;\n },\n ];\n};\n\nexport type AssetsControllerPriceChangedEvent = {\n type: `${typeof CONTROLLER_NAME}:priceChanged`;\n payload: [{ prices: Record<Caip19AssetId, AssetPrice> }];\n};\n\nexport type AssetsControllerAssetsDetectedEvent = {\n type: `${typeof CONTROLLER_NAME}:assetsDetected`;\n payload: [{ accountId: AccountId; assetIds: Caip19AssetId[] }];\n};\n\nexport type AssetsControllerEvents =\n | AssetsControllerStateChangeEvent\n | AssetsControllerBalanceChangedEvent\n | AssetsControllerPriceChangedEvent\n | AssetsControllerAssetsDetectedEvent;\n\ntype AllowedActions =\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | NetworkEnablementControllerGetStateAction\n // BackendWebsocketDataSource calls BackendWebSocketService\n | BackendWebSocketServiceActions;\n\ntype AllowedEvents =\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | NetworkEnablementControllerEvents\n | BackendWebSocketServiceEvents\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent;\n\nexport type AssetsControllerMessenger = Messenger<\n typeof CONTROLLER_NAME,\n AssetsControllerActions | AllowedActions,\n AssetsControllerEvents | AllowedEvents\n>;\n\n// ============================================================================\n// CONTROLLER OPTIONS\n// ============================================================================\n\nexport type AssetsControllerOptions = {\n messenger: AssetsControllerMessenger;\n state?: Partial<AssetsControllerState>;\n /** Default polling interval hint passed to data sources (ms) */\n defaultUpdateInterval?: number;\n /** Function to determine if the controller is enabled. Defaults to true. */\n isEnabled?: () => boolean;\n /**\n * API client for balance/price/metadata. The controller instantiates data sources\n * and uses them directly when this is provided.\n */\n queryApiClient: ApiPlatformClient;\n /** Optional configuration for RpcDataSource. */\n rpcDataSourceConfig?: RpcDataSourceConfig;\n};\n\n// ============================================================================\n// STATE METADATA\n// ============================================================================\n\nconst stateMetadata: StateMetadata<AssetsControllerState> = {\n assetsMetadata: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetsBalance: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetsPrice: {\n persist: false,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n customAssets: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n assetPreferences: {\n persist: true,\n includeInStateLogs: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\nfunction extractChainId(assetId: Caip19AssetId): ChainId {\n const parsed = parseCaipAssetType(assetId);\n return parsed.chainId;\n}\n\n/**\n * Normalizes all asset IDs in a DataResponse.\n * This is applied at the controller level to ensure consistent state\n * regardless of how data sources format their asset IDs.\n *\n * @param response - The DataResponse to normalize.\n * @returns The normalized DataResponse with checksummed EVM addresses.\n */\nfunction normalizeResponse(response: DataResponse): DataResponse {\n const normalized: DataResponse = {};\n\n if (response.assetsMetadata) {\n normalized.assetsMetadata = {};\n for (const [assetId, metadata] of Object.entries(response.assetsMetadata)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsMetadata[normalizedId] = metadata;\n }\n }\n\n if (response.assetsPrice) {\n normalized.assetsPrice = {};\n for (const [assetId, price] of Object.entries(response.assetsPrice)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsPrice[normalizedId] = price;\n }\n }\n\n if (response.assetsBalance) {\n normalized.assetsBalance = {};\n for (const [accountId, balances] of Object.entries(\n response.assetsBalance,\n )) {\n normalized.assetsBalance[accountId] = {};\n for (const [assetId, balance] of Object.entries(balances)) {\n const normalizedId = normalizeAssetId(assetId as Caip19AssetId);\n normalized.assetsBalance[accountId][normalizedId] = balance;\n }\n }\n }\n\n // Preserve detectedAssets with normalized asset IDs\n if (response.detectedAssets) {\n normalized.detectedAssets = {};\n for (const [accountId, assetIds] of Object.entries(\n response.detectedAssets,\n )) {\n normalized.detectedAssets[accountId] = assetIds.map((assetId) =>\n normalizeAssetId(assetId),\n );\n }\n }\n\n // Preserve errors (chain IDs don't need normalization)\n if (response.errors) {\n normalized.errors = { ...response.errors };\n }\n\n return normalized;\n}\n\n// ============================================================================\n// CONTROLLER IMPLEMENTATION\n// ============================================================================\n\n/**\n * AssetsController provides a unified interface for managing asset balances\n * across all blockchain networks (EVM and non-EVM) and all asset types.\n *\n * ## Core Responsibilities\n *\n * 1. **One-Time Fetch (Sync)**: For initial load, force refresh, or on-demand queries.\n * Uses `getAssets()`, `getAssetsBalance()`, etc. with `forceUpdate: true`.\n *\n * 2. **Async Subscriptions**: Subscribes to data sources for ongoing updates.\n * Data sources push updates via callbacks; the controller updates state.\n *\n * 3. **Dynamic Source Selection**: Routes requests to appropriate data sources\n * based on which chains they support. When active chains change, the controller\n * dynamically adjusts subscriptions.\n *\n * 4. **Keyring Lifecycle**: Listens to KeyringController unlock/lock events to\n * start/stop subscriptions when the wallet is unlocked or locked.\n *\n * ## Architecture\n *\n * - Data sources declare their supported chains (async, can change over time)\n * - Data sources are responsible for their own update mechanisms (WebSocket, polling, events)\n * - The controller does NOT manage polling - it simply receives pushed updates\n */\nexport class AssetsController extends BaseController<\n typeof CONTROLLER_NAME,\n AssetsControllerState,\n AssetsControllerMessenger\n> {\n /** Whether the controller is enabled */\n readonly #isEnabled: boolean;\n\n /** Default update interval hint passed to data sources */\n readonly #defaultUpdateInterval: number;\n\n readonly #controllerMutex = new Mutex();\n\n /**\n * Active balance subscriptions keyed by account ID.\n * Each account has one logical subscription that may span multiple data sources.\n * For example, if WebSocket covers chains A,B and RPC covers chain C,\n * the account subscribes to both data sources for its chains.\n */\n readonly #activeSubscriptions: Map<string, SubscriptionResponse> = new Map();\n\n /** Currently enabled chains from NetworkEnablementController */\n #enabledChains: Set<ChainId> = new Set();\n\n /**\n * Get the currently selected accounts from AccountTreeController.\n * This includes all accounts in the same group as the selected account\n * (EVM, Bitcoin, Solana, Tron, etc. that belong to the same logical account group).\n *\n * @returns Array of InternalAccount objects from the selected account group.\n */\n get #selectedAccounts(): InternalAccount[] {\n return this.messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n }\n\n readonly #backendWebsocketDataSource: BackendWebsocketDataSource;\n\n readonly #accountsApiDataSource: AccountsApiDataSource;\n\n readonly #snapDataSource: SnapDataSource;\n\n readonly #rpcDataSource: RpcDataSource;\n\n /**\n * Subscription balance data sources in assignment priority order (first that supports a chain gets it).\n *\n * @returns The four balance data source instances in priority order.\n */\n get #subscriptionBalanceDataSources(): [\n BackendWebsocketDataSource,\n AccountsApiDataSource,\n SnapDataSource,\n RpcDataSource,\n ] {\n return [\n this.#backendWebsocketDataSource,\n this.#accountsApiDataSource,\n this.#snapDataSource,\n this.#rpcDataSource,\n ];\n }\n\n readonly #priceDataSource: PriceDataSource;\n\n readonly #detectionMiddleware: DetectionMiddleware;\n\n readonly #tokenDataSource: TokenDataSource;\n\n constructor({\n messenger,\n state = {},\n defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS,\n isEnabled = (): boolean => true,\n queryApiClient,\n rpcDataSourceConfig,\n }: AssetsControllerOptions) {\n super({\n name: CONTROLLER_NAME,\n messenger,\n metadata: stateMetadata,\n state: {\n ...getDefaultAssetsControllerState(),\n ...state,\n },\n });\n\n this.#isEnabled = isEnabled();\n this.#defaultUpdateInterval = defaultUpdateInterval;\n const rpcConfig = rpcDataSourceConfig ?? {};\n\n const onActiveChainsUpdated = (\n dataSourceName: string,\n chains: ChainId[],\n previousChains: ChainId[],\n ): void =>\n this.handleActiveChainsUpdate(dataSourceName, chains, previousChains);\n\n this.#backendWebsocketDataSource = new BackendWebsocketDataSource({\n messenger: this.messenger,\n queryApiClient,\n onActiveChainsUpdated,\n });\n this.#accountsApiDataSource = new AccountsApiDataSource({\n queryApiClient,\n onActiveChainsUpdated,\n });\n this.#snapDataSource = new SnapDataSource({\n messenger: this.messenger,\n onActiveChainsUpdated,\n });\n this.#rpcDataSource = new RpcDataSource({\n messenger: this.messenger,\n onActiveChainsUpdated,\n ...rpcConfig,\n });\n this.#tokenDataSource = new TokenDataSource({\n queryApiClient,\n });\n this.#priceDataSource = new PriceDataSource({\n queryApiClient,\n });\n this.#detectionMiddleware = new DetectionMiddleware();\n\n if (!this.#isEnabled) {\n log('AssetsController is disabled, skipping initialization');\n return;\n }\n\n log('Initializing AssetsController', {\n defaultUpdateInterval: this.#defaultUpdateInterval,\n });\n\n this.#initializeState();\n this.#subscribeToEvents();\n this.#registerActionHandlers();\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n #initializeState(): void {\n const { enabledNetworkMap } = this.messenger.call(\n 'NetworkEnablementController:getState',\n );\n this.#enabledChains = this.#extractEnabledChains(enabledNetworkMap);\n\n log('Initialized state', {\n enabledNetworkMap,\n enabledChains: this.#enabledChains,\n });\n }\n\n /**\n * Extract enabled chains from enabledNetworkMap.\n * Returns CAIP-2 chain IDs for all enabled networks across all namespaces.\n *\n * Note: For EIP155 (EVM) chains, the reference is normalized to decimal format\n * to ensure consistency with CAIP-2 standard and API responses.\n *\n * @param enabledNetworkMap - The enabled network map from NetworkEnablementController.\n * @returns Set of CAIP-2 chain IDs for all enabled networks.\n */\n #extractEnabledChains(\n enabledNetworkMap: NetworkEnablementControllerState['enabledNetworkMap'],\n ): Set<ChainId> {\n const chains = new Set<ChainId>();\n\n for (const [namespace, networks] of Object.entries(enabledNetworkMap)) {\n for (const [reference, isEnabled] of Object.entries(networks)) {\n if (isEnabled) {\n // Check if reference is already a full CAIP-2 chain ID (contains colon)\n if (reference.includes(':')) {\n // Already a full chain ID, use as-is\n chains.add(reference as ChainId);\n } else {\n // Normalize EIP155 chain references from hex to decimal (CAIP-2 standard)\n const normalizedReference = this.#normalizeChainReference(\n namespace,\n reference,\n );\n chains.add(`${namespace}:${normalizedReference}`);\n }\n }\n }\n }\n return chains;\n }\n\n /**\n * Normalize chain reference to CAIP-2 standard format.\n * For EIP155, converts hex chain IDs to decimal.\n *\n * @param namespace - The chain namespace (e.g., \"eip155\").\n * @param reference - The chain reference (e.g., \"0x1\" or \"1\").\n * @returns The normalized chain reference in decimal format.\n */\n #normalizeChainReference(namespace: string, reference: string): string {\n if (namespace === 'eip155' && reference.startsWith('0x')) {\n // Convert hex to decimal for EIP155 chains\n return parseInt(reference, 16).toString();\n }\n return reference;\n }\n\n #subscribeToEvents(): void {\n // Subscribe to account group changes (when user switches between account groups like Account 1 -> Account 2)\n this.messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n () => {\n this.#handleAccountGroupChanged().catch(console.error);\n },\n );\n\n // Subscribe to network enablement changes (only enabledNetworkMap)\n this.messenger.subscribe(\n 'NetworkEnablementController:stateChange',\n ({ enabledNetworkMap }) => {\n this.#handleEnabledNetworksChanged(enabledNetworkMap).catch(\n console.error,\n );\n },\n );\n\n // Keyring lifecycle: start when unlocked, stop when locked\n this.messenger.subscribe('KeyringController:unlock', () => this.#start());\n this.messenger.subscribe('KeyringController:lock', () => this.#stop());\n }\n\n #registerActionHandlers(): void {\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n // ============================================================================\n // DATA SOURCE CHAIN MANAGEMENT\n // ============================================================================\n\n /**\n * Handle when a data source's supported chains change.\n * Used to refresh balance subscriptions and run a one-time fetch when a new chain is supported.\n *\n * - On any add/remove: re-subscribes to data sources so chain assignment stays correct.\n * - When chains are added: fetches balances for the new chains (for selected accounts on enabled networks).\n *\n * Controller does not store chains; sources report via this callback. previousChains is required for diff.\n *\n * @param dataSourceId - The identifier of the data source reporting the change.\n * @param activeChains - Currently active (supported and available) chain IDs for this source.\n * @param previousChains - Previous chains; used to compute added/removed.\n */\n handleActiveChainsUpdate(\n dataSourceId: string,\n activeChains: ChainId[],\n previousChains: ChainId[],\n ): void {\n log('Data source active chains changed', {\n dataSourceId,\n chainCount: activeChains.length,\n chains: activeChains,\n });\n\n const previous: ChainId[] = previousChains;\n\n const previousSet = new Set(previous);\n const addedChains = activeChains.filter((ch) => !previousSet.has(ch));\n const removedChains = previous.filter((ch) => !activeChains.includes(ch));\n\n if (addedChains.length > 0 || removedChains.length > 0) {\n // Refresh subscriptions to use updated data source availability\n this.#subscribeAssets();\n }\n\n // If chains were added and we have selected accounts, do one-time fetch\n if (addedChains.length > 0 && this.#selectedAccounts.length > 0) {\n const addedEnabledChains = addedChains.filter((chain) =>\n this.#enabledChains.has(chain),\n );\n if (addedEnabledChains.length > 0) {\n log('Fetching balances for newly added chains', { addedEnabledChains });\n this.getAssets(this.#selectedAccounts, {\n chainIds: addedEnabledChains,\n forceUpdate: true,\n }).catch((error) => {\n log('Failed to fetch balance for added chains', { error });\n });\n }\n }\n }\n\n // ============================================================================\n // MIDDLEWARE EXECUTION\n // ============================================================================\n\n /**\n * Execute middlewares with request/response context.\n *\n * @param middlewares - Middlewares to execute in order.\n * @param request - The data request.\n * @param initialResponse - Optional initial response (for enriching existing data).\n * @returns The final DataResponse after all middlewares have processed.\n */\n async #executeMiddlewares(\n middlewares: Middleware[],\n request: DataRequest,\n initialResponse: DataResponse = {},\n ): Promise<DataResponse> {\n const chain = middlewares.reduceRight<NextFunction>(\n (next, middleware) =>\n async (\n ctx,\n ): Promise<{\n request: DataRequest;\n response: DataResponse;\n getAssetsState: () => AssetsControllerStateInternal;\n }> => {\n try {\n return await middleware(ctx, next);\n } catch (error) {\n console.error('[AssetsController] Middleware failed:', error);\n return next(ctx);\n }\n },\n async (ctx) => ctx,\n );\n\n const result = await chain({\n request,\n response: initialResponse,\n getAssetsState: () => this.state as AssetsControllerStateInternal,\n });\n return result.response;\n }\n\n // ============================================================================\n // PUBLIC API: QUERY METHODS\n // ============================================================================\n\n async getAssets(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n dataTypes?: DataType[];\n },\n ): Promise<Record<AccountId, Record<Caip19AssetId, Asset>>> {\n const chainIds = options?.chainIds ?? [...this.#enabledChains];\n const assetTypes = options?.assetTypes ?? ['fungible'];\n const dataTypes = options?.dataTypes ?? ['balance', 'metadata', 'price'];\n\n // Collect custom assets for all requested accounts\n const customAssets: Caip19AssetId[] = [];\n for (const account of accounts) {\n const accountCustomAssets = this.getCustomAssets(account.id);\n customAssets.push(...accountCustomAssets);\n }\n\n if (options?.forceUpdate) {\n const request = this.#buildDataRequest(accounts, chainIds, {\n assetTypes,\n dataTypes,\n customAssets: customAssets.length > 0 ? customAssets : undefined,\n forceUpdate: true,\n });\n const response = await this.#executeMiddlewares(\n [\n this.#accountsApiDataSource.assetsMiddleware,\n this.#snapDataSource.assetsMiddleware,\n this.#rpcDataSource.assetsMiddleware,\n this.#detectionMiddleware.assetsMiddleware,\n this.#tokenDataSource.assetsMiddleware,\n this.#priceDataSource.assetsMiddleware,\n ],\n request,\n );\n await this.#updateState(response);\n }\n\n return this.#getAssetsFromState(accounts, chainIds, assetTypes);\n }\n\n async getAssetsBalance(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n },\n ): Promise<Record<AccountId, Record<Caip19AssetId, AssetBalance>>> {\n // Reuse getAssets with dataTypes: ['balance'] only\n const assets = await this.getAssets(accounts, {\n chainIds: options?.chainIds,\n assetTypes: options?.assetTypes,\n forceUpdate: options?.forceUpdate,\n dataTypes: ['balance', 'metadata'],\n });\n\n // Extract just the balance from each asset\n const result: Record<AccountId, Record<Caip19AssetId, AssetBalance>> = {};\n for (const [accountId, accountAssets] of Object.entries(assets)) {\n result[accountId] = {};\n for (const [assetId, asset] of Object.entries(accountAssets)) {\n if (asset.balance) {\n result[accountId][assetId as Caip19AssetId] = asset.balance;\n }\n }\n }\n\n return result;\n }\n\n getAssetMetadata(assetId: Caip19AssetId): AssetMetadata | undefined {\n return this.state.assetsMetadata[assetId] as AssetMetadata | undefined;\n }\n\n async getAssetsPrice(\n accounts: InternalAccount[],\n options?: {\n chainIds?: ChainId[];\n assetTypes?: AssetType[];\n forceUpdate?: boolean;\n },\n ): Promise<Record<Caip19AssetId, AssetPrice>> {\n const assets = await this.getAssets(accounts, {\n chainIds: options?.chainIds,\n assetTypes: options?.assetTypes,\n forceUpdate: options?.forceUpdate,\n dataTypes: ['price'],\n });\n\n // Extract just the price from each asset (flattened across accounts)\n const result: Record<Caip19AssetId, AssetPrice> = {};\n for (const accountAssets of Object.values(assets)) {\n for (const [assetId, asset] of Object.entries(accountAssets)) {\n if (asset.price) {\n result[assetId as Caip19AssetId] = asset.price;\n }\n }\n }\n\n return result;\n }\n\n // ============================================================================\n // CUSTOM ASSETS MANAGEMENT\n // ============================================================================\n\n /**\n * Add a custom asset for an account.\n * Custom assets are included in subscription and fetch operations.\n * Adding a custom asset also unhides it if it was previously hidden.\n *\n * @param accountId - The account ID to add the custom asset for.\n * @param assetId - The CAIP-19 asset ID to add.\n */\n async addCustomAsset(\n accountId: AccountId,\n assetId: Caip19AssetId,\n ): Promise<void> {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Adding custom asset', { accountId, assetId: normalizedAssetId });\n\n this.update((state) => {\n const customAssets = state.customAssets as Record<string, string[]>;\n if (!customAssets[accountId]) {\n customAssets[accountId] = [];\n }\n\n // Only add if not already present\n if (!customAssets[accountId].includes(normalizedAssetId)) {\n customAssets[accountId].push(normalizedAssetId);\n }\n\n // Unhide the asset if it was hidden (via assetPreferences)\n const prefs = state.assetPreferences[normalizedAssetId];\n if (prefs?.hidden) {\n delete prefs.hidden;\n if (Object.keys(prefs).length === 0) {\n delete state.assetPreferences[normalizedAssetId];\n }\n }\n });\n\n // Fetch data for the newly added custom asset\n const account = this.#selectedAccounts.find((a) => a.id === accountId);\n if (account) {\n const chainId = extractChainId(normalizedAssetId);\n await this.getAssets([account], {\n chainIds: [chainId],\n forceUpdate: true,\n });\n }\n }\n\n /**\n * Remove a custom asset from an account.\n *\n * @param accountId - The account ID to remove the custom asset from.\n * @param assetId - The CAIP-19 asset ID to remove.\n */\n removeCustomAsset(accountId: AccountId, assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Removing custom asset', { accountId, assetId: normalizedAssetId });\n\n this.update((state) => {\n if (state.customAssets[accountId]) {\n state.customAssets[accountId] = state.customAssets[accountId].filter(\n (id) => id !== normalizedAssetId,\n );\n\n // Clean up empty arrays\n if (state.customAssets[accountId].length === 0) {\n delete state.customAssets[accountId];\n }\n }\n });\n }\n\n /**\n * Get all custom assets for an account.\n *\n * @param accountId - The account ID to get custom assets for.\n * @returns Array of CAIP-19 asset IDs for the account's custom assets.\n */\n getCustomAssets(accountId: AccountId): Caip19AssetId[] {\n return this.state.customAssets[accountId] ?? [];\n }\n\n // ============================================================================\n // HIDDEN ASSETS MANAGEMENT\n // ============================================================================\n\n /**\n * Hide an asset globally.\n * Hidden assets are excluded from the asset list returned by getAssets.\n * The hidden state is stored in assetPreferences.\n *\n * @param assetId - The CAIP-19 asset ID to hide.\n */\n hideAsset(assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Hiding asset', { assetId: normalizedAssetId });\n\n this.update((state) => {\n if (!state.assetPreferences[normalizedAssetId]) {\n state.assetPreferences[normalizedAssetId] = {};\n }\n state.assetPreferences[normalizedAssetId].hidden = true;\n });\n }\n\n /**\n * Unhide an asset globally.\n *\n * @param assetId - The CAIP-19 asset ID to unhide.\n */\n unhideAsset(assetId: Caip19AssetId): void {\n const normalizedAssetId = normalizeAssetId(assetId);\n\n log('Unhiding asset', { assetId: normalizedAssetId });\n\n this.update((state) => {\n const prefs = state.assetPreferences[normalizedAssetId];\n if (prefs) {\n delete prefs.hidden;\n if (Object.keys(prefs).length === 0) {\n delete state.assetPreferences[normalizedAssetId];\n }\n }\n });\n }\n\n // ============================================================================\n // SUBSCRIPTIONS\n // ============================================================================\n\n /**\n * Subscribe to price updates for all assets held by the given accounts.\n * Polls PriceDataSource which fetches prices from balance state.\n *\n * @param accounts - Accounts to subscribe price updates for.\n * @param chainIds - Chain IDs to filter prices for.\n * @param options - Subscription options.\n * @param options.updateInterval - Polling interval in ms.\n */\n subscribeAssetsPrice(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n options: { updateInterval?: number } = {},\n ): void {\n const { updateInterval = this.#defaultUpdateInterval } = options;\n const subscriptionKey = 'ds:PriceDataSource';\n\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n const isUpdate = existingSubscription !== undefined;\n\n const subscribeReq: SubscriptionRequest = {\n request: this.#buildDataRequest(accounts, chainIds, {\n dataTypes: ['price'],\n updateInterval,\n }),\n subscriptionId: subscriptionKey,\n isUpdate,\n onAssetsUpdate: (response) =>\n this.handleAssetsUpdate(response, 'PriceDataSource'),\n getAssetsState: () => this.state,\n };\n\n this.#priceDataSource.subscribe(subscribeReq).catch(console.error);\n\n // Track subscription\n const subscription: SubscriptionResponse = {\n chains: chainIds,\n accountId: subscriptionKey,\n assetTypes: ['fungible'],\n dataTypes: ['price'],\n unsubscribe: () => {\n this.#activeSubscriptions.delete(subscriptionKey);\n },\n };\n\n this.#activeSubscriptions.set(subscriptionKey, subscription);\n }\n\n /**\n * Unsubscribe from price updates.\n */\n unsubscribeAssetsPrice(): void {\n const subscriptionKey = 'ds:PriceDataSource';\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n\n if (!existingSubscription) {\n return;\n }\n this.#priceDataSource.unsubscribe(subscriptionKey).catch(console.error);\n existingSubscription.unsubscribe();\n }\n\n // ============================================================================\n // STATE MANAGEMENT\n // ============================================================================\n\n async #updateState(response: DataResponse): Promise<void> {\n // Normalize asset IDs (checksum EVM addresses) before storing in state\n const normalizedResponse = normalizeResponse(response);\n\n const releaseLock = await this.#controllerMutex.acquire();\n\n try {\n const previousState = this.state;\n const previousPrices = { ...this.state.assetsPrice };\n // Use detectedAssets from response (assets without metadata)\n const detectedAssets: Record<AccountId, Caip19AssetId[]> =\n normalizedResponse.detectedAssets ?? {};\n\n // Track actual changes for logging\n const changedBalances: {\n accountId: string;\n assetId: string;\n oldAmount: string | undefined;\n newAmount: string;\n }[] = [];\n const changedMetadata: string[] = [];\n\n this.update((state) => {\n // Use type assertions to avoid deep type instantiation issues with Immer Draft types\n const metadata = state.assetsMetadata as Record<string, AssetMetadata>;\n const balances = state.assetsBalance as Record<\n string,\n Record<string, AssetBalance>\n >;\n const prices = state.assetsPrice as Record<string, AssetPrice>;\n\n if (normalizedResponse.assetsMetadata) {\n for (const [key, value] of Object.entries(\n normalizedResponse.assetsMetadata,\n )) {\n if (\n !isEqual(\n previousState.assetsMetadata[key as Caip19AssetId],\n value,\n )\n ) {\n changedMetadata.push(key);\n }\n metadata[key] = value;\n }\n }\n\n if (normalizedResponse.assetsBalance) {\n for (const [accountId, accountBalances] of Object.entries(\n normalizedResponse.assetsBalance,\n )) {\n const previousBalances =\n previousState.assetsBalance[accountId] ?? {};\n\n if (!balances[accountId]) {\n balances[accountId] = {};\n }\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n const previousBalance = previousBalances[\n assetId as Caip19AssetId\n ] as { amount: string } | undefined;\n const balanceData = balance as { amount: string };\n const newAmount = balanceData.amount;\n const oldAmount = previousBalance?.amount;\n\n // Track if balance actually changed\n if (oldAmount !== newAmount) {\n changedBalances.push({\n accountId,\n assetId,\n oldAmount,\n newAmount,\n });\n }\n }\n\n Object.assign(balances[accountId], accountBalances);\n }\n }\n\n // Update prices in state\n if (normalizedResponse.assetsPrice) {\n for (const [key, value] of Object.entries(\n normalizedResponse.assetsPrice,\n )) {\n prices[key] = value;\n }\n }\n });\n\n // Calculate changed prices\n const changedPriceAssets: string[] = normalizedResponse.assetsPrice\n ? Object.keys(normalizedResponse.assetsPrice).filter(\n (assetId) =>\n !isEqual(\n previousPrices[assetId as Caip19AssetId],\n normalizedResponse.assetsPrice?.[assetId as Caip19AssetId],\n ),\n )\n : [];\n\n // Log only actual changes\n if (\n changedBalances.length > 0 ||\n changedMetadata.length > 0 ||\n changedPriceAssets.length > 0\n ) {\n log('State updated', {\n changedBalances:\n changedBalances.length > 0 ? changedBalances : undefined,\n changedMetadataCount:\n changedMetadata.length > 0 ? changedMetadata.length : undefined,\n changedPricesCount:\n changedPriceAssets.length > 0\n ? changedPriceAssets.length\n : undefined,\n newAssets:\n Object.keys(detectedAssets).length > 0\n ? Object.entries(detectedAssets).map(([accountId, assets]) => ({\n accountId,\n assets,\n }))\n : undefined,\n });\n }\n\n // Publish balance changed events\n for (const change of changedBalances) {\n this.messenger.publish('AssetsController:balanceChanged', {\n accountId: change.accountId,\n assetId: change.assetId as Caip19AssetId,\n previousAmount: change.oldAmount ?? '0',\n newAmount: change.newAmount,\n });\n }\n\n // Publish price changed event with full price data\n if (changedPriceAssets.length > 0 && normalizedResponse.assetsPrice) {\n // Build prices object with only changed prices\n const changedPrices: Record<Caip19AssetId, AssetPrice> = {};\n for (const assetId of changedPriceAssets) {\n const price =\n normalizedResponse.assetsPrice[assetId as Caip19AssetId];\n if (price) {\n changedPrices[assetId as Caip19AssetId] = price;\n }\n }\n this.messenger.publish('AssetsController:priceChanged', {\n prices: changedPrices,\n });\n }\n\n // Publish assets detected events\n for (const [accountId, assetIds] of Object.entries(detectedAssets)) {\n if (assetIds.length > 0) {\n this.messenger.publish('AssetsController:assetsDetected', {\n accountId,\n assetIds,\n });\n }\n }\n } finally {\n releaseLock();\n }\n }\n\n #getAssetsFromState(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n assetTypes: AssetType[],\n ): Record<AccountId, Record<Caip19AssetId, Asset>> {\n const result: Record<AccountId, Record<Caip19AssetId, Asset>> = {};\n // Convert to Sets for O(1) lookups\n const chainIdSet = new Set(chainIds);\n const assetTypeSet = new Set(assetTypes);\n\n for (const account of accounts) {\n result[account.id] = {};\n\n const accountBalances = this.state.assetsBalance[account.id] ?? {};\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n const typedAssetId = assetId as Caip19AssetId;\n\n const metadataRaw = this.state.assetsMetadata[typedAssetId];\n\n // Skip assets without metadata\n if (!metadataRaw) {\n continue;\n }\n\n const metadata = metadataRaw;\n\n // Skip hidden assets (assetPreferences)\n const prefs = this.state.assetPreferences[typedAssetId];\n if (prefs?.hidden) {\n continue;\n }\n\n const assetChainId = extractChainId(typedAssetId);\n\n if (!chainIdSet.has(assetChainId)) {\n continue;\n }\n\n // Filter by asset type\n const tokenAssetType = this.#tokenStandardToAssetType(metadata.type);\n if (!assetTypeSet.has(tokenAssetType)) {\n continue;\n }\n\n const typedBalance = balance;\n const priceRaw = this.state.assetsPrice[typedAssetId];\n const price: AssetPrice = priceRaw ?? {\n price: 0,\n lastUpdated: 0,\n };\n\n // Compute fiat value using BigNumber for precision\n // Note: typedBalance.amount is already in human-readable format (e.g., \"1\" for 1 ETH)\n // so we do NOT divide by 10^decimals here\n const balanceAmount = new BigNumberJS(typedBalance.amount || '0');\n const fiatValue = balanceAmount\n .multipliedBy(price.price || 0)\n .toNumber();\n\n const asset: Asset = {\n id: typedAssetId,\n chainId: assetChainId,\n balance: typedBalance,\n metadata,\n price,\n fiatValue,\n };\n\n result[account.id][typedAssetId] = asset;\n }\n }\n\n return result;\n }\n\n /**\n * Maps a token standard to its corresponding asset type.\n *\n * @param tokenStandard - The token standard from metadata.\n * @returns The corresponding asset type.\n */\n #tokenStandardToAssetType(tokenStandard: string): AssetType {\n switch (tokenStandard) {\n case 'native':\n case 'erc20':\n case 'spl':\n return 'fungible';\n case 'erc721':\n return 'nft';\n case 'erc1155':\n // ERC1155 can be either fungible or non-fungible, treat as collectible\n return 'collectible';\n default:\n // Unknown standards default to fungible\n return 'fungible';\n }\n }\n\n // ============================================================================\n // START / STOP\n // ============================================================================\n\n /**\n * Start asset tracking: subscribe to updates and fetch current balances.\n * Called when app opens, account changes, or keyring unlocks.\n */\n #start(): void {\n log('Starting asset tracking', {\n selectedAccountCount: this.#selectedAccounts.length,\n enabledChainCount: this.#enabledChains.size,\n });\n\n this.#subscribeAssets();\n if (this.#selectedAccounts.length > 0) {\n this.getAssets(this.#selectedAccounts, {\n chainIds: [...this.#enabledChains],\n forceUpdate: true,\n }).catch((error) => {\n log('Failed to fetch assets', error);\n });\n }\n }\n\n /**\n * Stop asset tracking: unsubscribe from all updates.\n * Called when app closes or keyring locks.\n */\n #stop(): void {\n log('Stopping asset tracking', {\n activeSubscriptionCount: this.#activeSubscriptions.size,\n hasPriceSubscription: this.#activeSubscriptions.has('ds:PriceDataSource'),\n });\n\n // Stop price subscription first (uses direct messenger call)\n this.unsubscribeAssetsPrice();\n\n // Stop balance subscriptions by properly notifying data sources via messenger\n // This ensures data sources stop their polling timers\n // Convert to array first to avoid modifying map during iteration\n const subscriptionKeys = [...this.#activeSubscriptions.keys()];\n for (const subscriptionKey of subscriptionKeys) {\n if (subscriptionKey.startsWith('ds:')) {\n const sourceId = subscriptionKey.slice(3);\n const source = this.#subscriptionBalanceDataSources.find(\n (ds) => ds.getName() === sourceId,\n );\n if (source) {\n this.#unsubscribeDataSource(source);\n }\n }\n }\n this.#activeSubscriptions.clear();\n }\n\n /**\n * Subscribe to asset updates for all selected accounts.\n */\n #subscribeAssets(): void {\n if (this.#selectedAccounts.length === 0) {\n return;\n }\n\n // Subscribe to balance updates (batched by data source)\n this.#subscribeAssetsBalance(this.#selectedAccounts, [\n ...this.#enabledChains,\n ]);\n\n // Subscribe to price updates for all assets held by selected accounts\n this.subscribeAssetsPrice(this.#selectedAccounts, [...this.#enabledChains]);\n }\n\n /**\n * Subscribe to balance updates for the given accounts and chains.\n *\n * Strategy to minimize data source calls:\n * 1. Collect all chains to subscribe based on enabled networks\n * 2. Map chains to accounts based on their scopes\n * 3. Split by data source (ordered by priority) - each data source gets ONE subscription\n *\n * This ensures we make minimal subscriptions to each data source while covering\n * all accounts and chains.\n *\n * @param accounts - Accounts to subscribe balance updates for.\n * @param chainIds - Chain IDs to subscribe for.\n */\n #subscribeAssetsBalance(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n ): void {\n const chainToAccounts = this.#buildChainToAccountsMap(\n accounts,\n new Set(chainIds),\n );\n const remainingChains = new Set(chainToAccounts.keys());\n\n for (const source of this.#subscriptionBalanceDataSources) {\n const availableChains = new Set(source.getActiveChainsSync());\n const assignedChains: ChainId[] = [];\n\n for (const chainId of remainingChains) {\n if (availableChains.has(chainId)) {\n assignedChains.push(chainId);\n remainingChains.delete(chainId);\n }\n }\n\n if (assignedChains.length === 0) {\n this.#unsubscribeDataSource(source);\n continue;\n }\n\n const seenIds = new Set<string>();\n const accountsForSource = assignedChains\n .flatMap((chainId) => chainToAccounts.get(chainId) ?? [])\n .filter(\n (account) =>\n !seenIds.has(account.id) && (seenIds.add(account.id), true),\n );\n if (accountsForSource.length > 0) {\n this.#subscribeDataSource(source, accountsForSource, assignedChains);\n }\n }\n }\n\n /**\n * Build a mapping of chainId -> accounts that support that chain.\n * Only includes chains that are in the chainsToSubscribe set.\n *\n * @param accounts - Array of accounts to build mapping for.\n * @param chainsToSubscribe - Set of chain IDs to include in the mapping.\n * @returns Map of chainId to array of accounts that support that chain.\n */\n #buildChainToAccountsMap(\n accounts: InternalAccount[],\n chainsToSubscribe: Set<ChainId>,\n ): Map<ChainId, InternalAccount[]> {\n const chainToAccounts = new Map<ChainId, InternalAccount[]>();\n for (const account of accounts) {\n for (const chainId of this.#getEnabledChainsForAccount(account)) {\n if (!chainsToSubscribe.has(chainId)) {\n continue;\n }\n let list = chainToAccounts.get(chainId);\n if (!list) {\n list = [];\n chainToAccounts.set(chainId, list);\n }\n list.push(account);\n }\n }\n return chainToAccounts;\n }\n\n /**\n * Subscribe to a specific data source with accounts and chains.\n * Uses the data source name as the subscription key for batching.\n *\n * @param source - The balance data source instance.\n * @param accounts - Array of accounts to subscribe for.\n * @param chains - Array of chain IDs to subscribe for.\n */\n #subscribeDataSource(\n source: AbstractDataSource<string, DataSourceState>,\n accounts: InternalAccount[],\n chains: ChainId[],\n ): void {\n const sourceId = source.getName();\n const subscriptionKey = `ds:${sourceId}`;\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n const isUpdate = existingSubscription !== undefined;\n\n log('Subscribe to data source', {\n sourceId,\n subscriptionKey,\n isUpdate,\n accountCount: accounts.length,\n chainCount: chains.length,\n });\n\n const subscribeReq: SubscriptionRequest = {\n request: this.#buildDataRequest(accounts, chains, {\n assetTypes: ['fungible'],\n dataTypes: ['balance'],\n updateInterval: this.#defaultUpdateInterval,\n }),\n subscriptionId: subscriptionKey,\n isUpdate,\n onAssetsUpdate: (response) => this.handleAssetsUpdate(response, sourceId),\n getAssetsState: () => this.state,\n };\n\n source.subscribe(subscribeReq).catch((error) => {\n console.error(\n `[AssetsController] Failed to subscribe to '${sourceId}':`,\n error,\n );\n });\n\n // Track subscription\n const subscription: SubscriptionResponse = {\n chains,\n accountId: subscriptionKey,\n assetTypes: ['fungible'],\n dataTypes: ['balance'],\n unsubscribe: () => {\n this.#activeSubscriptions.delete(subscriptionKey);\n },\n };\n\n this.#activeSubscriptions.set(subscriptionKey, subscription);\n }\n\n /**\n * Unsubscribe from a data source if we have an active subscription.\n *\n * @param source - The balance data source instance to unsubscribe from.\n */\n #unsubscribeDataSource(\n source: AbstractDataSource<string, DataSourceState>,\n ): void {\n const subscriptionKey = `ds:${source.getName()}`;\n const existingSubscription = this.#activeSubscriptions.get(subscriptionKey);\n\n if (existingSubscription) {\n source.unsubscribe(subscriptionKey).catch(() => undefined);\n existingSubscription.unsubscribe();\n }\n }\n\n // ============================================================================\n // HELPERS\n // ============================================================================\n\n /**\n * Build a DataRequest with accountsWithSupportedChains (enabled chains ∩ account scope ∩ requested chainIds).\n *\n * @param accounts - Accounts to include.\n * @param chainIds - Requested chain IDs (e.g. enabled chains or subset).\n * @param partial - Rest of the request (dataTypes, assetTypes, etc.).\n * @returns DataRequest with accountsWithSupportedChains and chainIds.\n */\n #buildDataRequest(\n accounts: InternalAccount[],\n chainIds: ChainId[],\n partial: Partial<\n Omit<DataRequest, 'accountsWithSupportedChains' | 'chainIds'>\n > = {},\n ): DataRequest {\n const chainIdSet = new Set(chainIds);\n const accountsWithSupportedChains: AccountWithSupportedChains[] =\n accounts.map((account) => ({\n account,\n supportedChains: this.#getEnabledChainsForAccount(account).filter(\n (chain) => chainIdSet.has(chain),\n ),\n }));\n return {\n accountsWithSupportedChains,\n chainIds,\n ...partial,\n } as DataRequest;\n }\n\n /**\n * Get the chains that an account supports based on its scopes.\n * Returns the intersection of the account's scopes and the enabled chains.\n *\n * @param account - The account to get supported chains for.\n * @returns Array of ChainIds that the account supports and are enabled.\n */\n #getEnabledChainsForAccount(account: InternalAccount): ChainId[] {\n // Account scopes are CAIP-2 chain IDs like \"eip155:1\", \"solana:mainnet\", \"bip122:...\"\n const scopes = account.scopes ?? [];\n const result: ChainId[] = [];\n\n for (const scope of scopes) {\n const [namespace, reference] = (scope as string).split(':');\n\n // Wildcard scope (e.g., \"eip155:0\" means all enabled chains in that namespace)\n if (reference === '0') {\n for (const chain of this.#enabledChains) {\n if (chain.startsWith(`${namespace}:`)) {\n result.push(chain);\n }\n }\n } else if (namespace === 'eip155' && reference?.startsWith('0x')) {\n // Normalize hex to decimal for EIP155\n result.push(`eip155:${parseInt(reference, 16)}` as ChainId);\n } else {\n result.push(scope);\n }\n }\n\n return result;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n async #handleAccountGroupChanged(): Promise<void> {\n const accounts = this.#selectedAccounts;\n\n log('Account group changed', {\n accountCount: accounts.length,\n accountIds: accounts.map((a) => a.id),\n });\n\n // Subscribe and fetch for the new account group\n this.#subscribeAssets();\n if (accounts.length > 0) {\n await this.getAssets(accounts, {\n chainIds: [...this.#enabledChains],\n forceUpdate: true,\n });\n }\n }\n\n async #handleEnabledNetworksChanged(\n enabledNetworkMap: NetworkEnablementControllerState['enabledNetworkMap'],\n ): Promise<void> {\n const previousChains = this.#enabledChains;\n this.#enabledChains = this.#extractEnabledChains(enabledNetworkMap);\n\n // Find newly enabled chains (in new set but not in previous)\n const addedChains: ChainId[] = [];\n for (const chain of this.#enabledChains) {\n if (!previousChains.has(chain)) {\n addedChains.push(chain);\n }\n }\n\n // Find disabled chains to clean up (in previous but not in new)\n const removedChains: ChainId[] = [];\n for (const chain of previousChains) {\n if (!this.#enabledChains.has(chain)) {\n removedChains.push(chain);\n }\n }\n\n log('Enabled networks changed', {\n previousCount: previousChains.size,\n newCount: this.#enabledChains.size,\n addedChains,\n removedChains,\n });\n\n // Note: We intentionally do NOT delete balance data for disabled chains.\n // Users may want to see historical balances even if the network is currently disabled.\n // The data will simply not be updated until the network is re-enabled.\n\n // Refresh subscriptions for new chain set\n this.#subscribeAssets();\n\n // Do one-time fetch for newly enabled chains\n if (addedChains.length > 0 && this.#selectedAccounts.length > 0) {\n await this.getAssets(this.#selectedAccounts, {\n chainIds: addedChains,\n forceUpdate: true,\n });\n }\n }\n\n /**\n * Handle assets updated from a data source.\n * Called via the onAssetsUpdate callback passed in SubscriptionRequest when the controller subscribes to a data source.\n * Enriches the response with token metadata (via middlewares) before updating state.\n *\n * @param response - The data response with updated assets\n * @param sourceId - The data source ID reporting the update\n * @param request - Optional original request for context when enriching\n */\n async handleAssetsUpdate(\n response: DataResponse,\n sourceId: string,\n request?: DataRequest,\n ): Promise<void> {\n log('Assets updated from data source', {\n sourceId,\n hasBalance: Boolean(response.assetsBalance),\n hasPrice: Boolean(response.assetsPrice),\n });\n\n // Run through enrichment middlewares (Event Stack: Detection → Token → Price)\n // Include 'metadata' in dataTypes so TokenDataSource runs to enrich detected assets\n const enrichedResponse = await this.#executeMiddlewares(\n [\n this.#detectionMiddleware.assetsMiddleware,\n this.#tokenDataSource.assetsMiddleware,\n this.#priceDataSource.assetsMiddleware,\n ],\n request ?? {\n accountsWithSupportedChains: [],\n chainIds: [],\n dataTypes: ['balance', 'metadata', 'price'],\n },\n response,\n );\n\n await this.#updateState(enrichedResponse);\n }\n\n // ============================================================================\n // CLEANUP\n // ============================================================================\n\n destroy(): void {\n log('Destroying AssetsController', {\n dataSourceCount: this.#subscriptionBalanceDataSources.length,\n subscriptionCount: this.#activeSubscriptions.size,\n });\n\n // Destroy instantiated data sources\n this.#backendWebsocketDataSource?.destroy?.();\n this.#accountsApiDataSource?.destroy?.();\n this.#snapDataSource?.destroy?.();\n if (\n this.#rpcDataSource &&\n 'destroy' in this.#rpcDataSource &&\n typeof (this.#rpcDataSource as { destroy: () => void }).destroy ===\n 'function'\n ) {\n (this.#rpcDataSource as { destroy: () => void }).destroy();\n }\n\n // Stop all active subscriptions\n this.#stop();\n\n // Unregister action handlers\n this.messenger.unregisterActionHandler('AssetsController:getAssets');\n this.messenger.unregisterActionHandler('AssetsController:getAssetsBalance');\n this.messenger.unregisterActionHandler('AssetsController:getAssetMetadata');\n this.messenger.unregisterActionHandler('AssetsController:getAssetsPrice');\n this.messenger.unregisterActionHandler('AssetsController:addCustomAsset');\n this.messenger.unregisterActionHandler(\n 'AssetsController:removeCustomAsset',\n );\n this.messenger.unregisterActionHandler('AssetsController:getCustomAssets');\n this.messenger.unregisterActionHandler('AssetsController:hideAsset');\n this.messenger.unregisterActionHandler('AssetsController:unhideAsset');\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/assets-controller",
3
- "version": "1.0.0-preview-cbcea9611",
3
+ "version": "1.0.0-preview-bc3c2ef97",
4
4
  "description": "Tracks assets balances/prices and handles token detection across all digital assets",
5
5
  "keywords": [
6
6
  "MetaMask",