All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Bump
@metamask/assets-controllersfrom^104.0.0to^104.1.0(#8509) - Bump
@metamask/keyring-apifrom^21.6.0to^23.0.1(#8464) - Bump
@metamask/keyring-internal-apifrom^10.0.0to^10.1.1(#8464) - Bump
@metamask/keyring-snap-clientfrom^8.2.0to^9.0.1(#8464) - Bump
@metamask/transaction-controllerfrom^64.2.0to^64.3.0(#8482)
- BREAKING:
AssetsControllerMessengernow requires theAccountsControllerGetSelectedAccountActionallowed action (#8430)- Used as a fallback in
#getSelectedAccounts()whenAccountTreeControllerhas not yet initialized. - Consumers must register
AccountsController:getSelectedAccounton the messenger.
- Used as a fallback in
- BREAKING:
AssetsControllerMessengernow requires theTransactionControllerUnapprovedTransactionAddedEventallowed event (#8430)AssetsControllersubscribes toTransactionController:unapprovedTransactionAddedto refresh balances for the account initiating a transaction (e.g. for gas estimations).- Consumers must allow
TransactionController:unapprovedTransactionAddedon the messenger.
- Added
isOnboardedoption toAssetsControllerOptionsandRpcDataSourceConfig(#8430)- When
isOnboardedreturnsfalse,RpcDataSourceskipsfetchandsubscribecalls, preventing on-chain RPC calls before onboarding is complete. - Defaults to
() => trueso existing consumers are unaffected.
- When
- Bump
@metamask/account-tree-controllerfrom^7.0.0to^7.1.0(#8472)
- Bump
@metamask/transaction-controllerfrom^64.0.0to^64.2.0(#8432, #8447) - Bump
@metamask/base-controllerfrom^9.0.1to^9.1.0(#8457) - Bump
@metamask/assets-controllersfrom^103.1.1to^104.0.0(#8466)
AssetsControllernow re-subscribes to all data sources whenAccountTreeControllerstate changes after initial startup, ensuring snap accounts and their chains are included (#8430)- Previously,
#start()would create subscriptions before snap accounts were available, and its idempotency guard prevented re-subscription when the full account list arrived. - Added
#handleAccountTreeStateChange()which forces a full re-subscription and re-fetch when the account tree updates, picking up all accounts including snaps. - Added
AccountsController:getSelectedAccountas a fallback in#getSelectedAccounts()for when the account tree is not yet initialized.
- Previously,
TokenDataSourceno longer filters out user-imported custom assets with theMIN_TOKEN_OCCURRENCESspam filter or Blockaid bulk scan (#8430)- Tokens present in
customAssetsstate now bypass the EVM occurrence threshold and non-EVM Blockaid scan, ensuring manually imported assets always appear.
- Tokens present in
BackendWebsocketDataSourcenow properly releases chains toAccountsApiDataSourcewhen the websocket is disconnected or disabled (#8430)- Previously,
BackendWebsocketDataSourceeagerly claimed all supported chains on initialization regardless of connection state, preventingAccountsApiDataSourcefrom polling. - Chains are now only claimed when the websocket is connected. On disconnect, chains are released so the chain-claiming loop assigns them to
AccountsApiDataSourcefor polling fallback. On reconnect, chains are reclaimed.
- Previously,
AssetsControllerno longer silently skips asset fetching on startup for returning users (#8412)- Previously,
#start()was called at keyring unlock beforeAccountTreeController.init()had built the account tree, causing#selectedAccountsto return an empty array and all subscriptions and fetches to be skipped.selectedAccountGroupChangedoes not fire when the persisted selected group is unchanged, leaving the controller idle. - Now subscribes to
AccountTreeController:stateChange(the base-controller event guaranteed to fire wheninit()callsthis.update()), so the controller re-evaluates its active state once accounts are available. #start()is now idempotent: it returns early when accounts or chains are not yet available, and when subscriptions are already active, preventing duplicate fetches from repeated events.
- Previously,
- BREAKING:
TokenDetectornow fetches the token list directly from the Tokens API (/v3/chains/{chain}/assets) via a newTokensApiClientinstead of reading fromTokenListController:getState(#8385)TokenDetectorMessengertype has been removed;TokenDetectorconstructor now takes aTokensApiClientinstance as its second argumentRpcDataSourceno longer requiresTokenListController:getState—GetTokenListStatehas been removed fromRpcDataSourceAllowedActionsandAssetsControllerAllowedActions- Unknown ERC-20 metadata is no longer looked up from the token list as a fallback in
RpcDataSource;TokenDataSourcehandles enrichment downstream
- Split
getAssetsfetch pipeline into a fast awaited path and a parallel fire-and-forget background path to reduce perceived latency on unlock and onboarding (#8383)- Fast pipeline: AccountsApi + StakedBalance → Detection → Token + Price (awaited, committed to state immediately)
- Background pipeline: Snap + RPC run in parallel → Detection → Token + Price when basic functionality is enabled; when disabled (RPC-only mode), Token + Price are omitted (fire-and-forget merge)
handleAssetsUpdateskips token/price enrichment and stripsmetadata/pricefrom the effective request when basic functionality is disabled (RPC-only mode)setSelectedCurrencyno longer triggers a price refresh viagetAssetswhen basic functionality is disabled
PriceDataSourcenow batches spot-price API requests in chunks of 50 usingreduceInBatchesSeriallyto avoid DynamoDB batch-limit errors (#8383)TokenDataSourcenow batches token metadata API requests in chunks of 50 usingreduceInBatchesSeriallyto avoid DynamoDB batch-limit errors (#8383)PriceDataSourcefilters out all syntheticslip44:NUMBER-*staking-position asset IDs before calling the Price API (#8383)TokenDataSourcefilters EVM ERC-20 tokens byoccurrences >= 3and treats missing occurrences as 0 (#8383)- Bump
@metamask/keyring-controllerfrom^25.1.1to^25.2.0(#8363) - Bump
@metamask/messengerfrom^1.0.0to^1.1.1(#8364, #8373)
- BREAKING:
TokenDataSourceconstructor now takes(messenger, options)instead of(options);messengermust be the sameAssetsControllerMessengerused byAssetsControllerso token metadata enrichment can callPhishingController:bulkScanTokens(#8329)- Clients must now provide
PhishingController:bulkScanTokenspermission when constructing the controller messenger
- Clients must now provide
TokenDataSourceremoves tokens flagged malicious by Blockaid (viaPhishingController:bulkScanTokens) before merging metadata, instead of filtering non-native tokens by a minimum occurrence count (#8329)- Bump
@metamask/assets-controllersfrom^103.1.0to^103.1.1(#8359) - Bump
@metamask/network-enablement-controllerfrom^5.0.1to^5.0.2(#8359) - Bump
@metamask/phishing-controllerfrom^17.1.0to^17.1.1(#8359) - Bump
@metamask/transaction-controllerfrom^63.3.1to^64.0.0(#8359)
- Bump
@metamask/controller-utilsfrom^11.19.0to^11.20.0(#8344) - Hide native tokens on Tempo networks (testnet and mainnet) in
getAssetsmethod (#7882) - Bump
@metamask/assets-controllersfrom^103.0.0to^103.1.0(#8355)
- Bump
@metamask/snaps-controllersfrom^17.2.0to^19.0.0(#8319) - Bump
@metamask/snaps-utilsfrom^11.7.0to^12.1.2(#8319) - Bump
@metamask/account-tree-controllerfrom^6.0.0to^7.0.0(#8325) - Bump
@metamask/assets-controllersfrom^102.0.0to^103.0.0(#8325)
- Add Sentry traces for Assets Health dashboard (#8310)
AssetsDataSourceTiming— per-source latency for each middleware in the fetch pipelineAssetsDataSourceError— tracks middleware failures with source names and error countsAssetsFullFetch— end-to-end fetch timing with asset/price/chain/account countsAssetsUpdatePipeline— enrichment pipeline timing for pushed data source updatesAssetsSubscriptionError— subscription failure tracking per data sourceAssetsStateSize— entry counts for balances, metadata, prices, custom assets, unique assets, and network count (once on app start)AggregatedBalanceSelector— balance selector computation time with asset/network/account counts- Add optional
traceparameter togetAggregatedBalanceForAccountselector
- Bump
@metamask/account-tree-controllerfrom^5.0.1to^6.0.0(#8317) - Bump
@metamask/assets-controllersfrom^101.0.1to^102.0.0(#8317) - Bump
@metamask/base-controllerfrom^9.0.0to^9.0.1(#8317) - Bump
@metamask/client-controllerfrom^1.0.0to^1.0.1(#8317) - Bump
@metamask/core-backendfrom^6.2.0to^6.2.1(#8317) - Bump
@metamask/keyring-controllerfrom^25.1.0to^25.1.1(#8317) - Bump
@metamask/messengerfrom^0.3.0to^1.0.0(#8317) - Bump
@metamask/network-controllerfrom^30.0.0to^30.0.1(#8317) - Bump
@metamask/network-enablement-controllerfrom^5.0.0to^5.0.1(#8317) - Bump
@metamask/permission-controllerfrom^12.2.1to^12.3.0(#8317) - Bump
@metamask/polling-controllerfrom^16.0.3to^16.0.4(#8317) - Bump
@metamask/preferences-controllerfrom^23.0.0to^23.1.0(#8317) - Bump
@metamask/transaction-controllerfrom^63.1.0to^63.3.1(#8301, #8313, #8317)
- Refactored
BalanceFetcherandRpcDataSourceto ensure the correctassetIdis used for EVM native assets that are not ETH (#8284)
- EVM RPC balance pipeline (
RpcDataSource,BalanceFetcher,TokenDetector) no longer falls back to 18 decimals for ERC-20 when decimals are unknown; human-readable balances anddetectedBalancesentries are omitted until decimals are available from state, token list metadata, or on-chaindecimals()(native token handling unchanged) (#8267) - Bump
@metamask/keyring-apifrom^21.5.0to^21.6.0(#8259) - Bump
@metamask/transaction-controllerfrom^63.0.0to^63.1.0(#8272)
- fix: move
selectedAccountGroupto top-level persisted state (#8245)
- Per-data-source latency inside parallel middlewares:
durationByDataSourcenow includes entries such asParallelMiddleware.TokenDataSource,ParallelMiddleware.PriceDataSource, andParallelBalanceMiddleware.<SourceName>(ms), so traces can see which internal sources contributed toParallelMiddlewareandParallelBalanceMiddlewaretimings. (#8147)
- BREAKING: First-init-fetch measurement moved from MetaMetrics to Sentry. Option
trackMetaMetricsEventis replaced bytrace: TraceCallback. TypeAssetsControllerFirstInitFetchMetaMetricsPayloadis removed; trace request data is not typed in this package. (#8147) TokenDataSourcenow always includes native token asset IDs (fromNetworkEnablementController.nativeAssetIdentifiers) in metadata fetch calls, ensuring native tokens always have up-to-date metadata (#8227)TokenDataSourcenow filters out non-native tokens with fewer than 3 occurrences from metadata responses, and also removes their balances and detected asset entries, to prevent spam tokens from being stored in state (#8227)TokenDataSourcenow requestsincludeOccurrenceswhen fetching v3 asset metadata (#8227)- Bump
@metamask/assets-controllersfrom^101.0.0to^101.0.1(#8232) - Bump
@metamask/core-backendfrom^6.1.1to^6.2.0(#8232)
- Bump
@metamask/network-enablement-controllerfrom^4.2.0to^5.0.0(#8225) - Bump
@metamask/permission-controllerfrom^12.2.0to^12.2.1(#8225) BridgeExchangeRatesFormattype now uses canonical@metamask/assets-controllersstate types instead of locally-defined bridge rate entry types (#8175)- Bump
@metamask/account-tree-controllerfrom^5.0.0to^5.0.1(#8162) - Bump
@metamask/assets-controllersfrom^100.2.0to^101.0.0(#8162, #8225) - Bump
@metamask/core-backendfrom^6.1.0to^6.1.1(#8162) - Bump
@metamask/transaction-controllerfrom^62.21.0to^63.0.0(#8217, #8225)
- Preserve custom asset metadata (symbol, name, decimals, image) in
AssetsControllerwhen the API returns an empty response for an unknown token, preventing incorrect balance calculations and display for user-deployed tokens added viawallet_watchAsset(#8202) - Include custom asset token addresses in
RpcDataSourcebalance fetches so that on-chain balances are retrieved immediately after token import viaaddCustomAsset(#8202)
usdPriceis not included in asset price data (#8123)- Add
getStateForTransactionPay()method andAssetsController:getStateForTransactionPaymessenger action. Returns state in the legacy format expected by transaction-pay-controller (TokenBalancesController, AccountTrackerController, TokensController, TokenRatesController, CurrencyRateController shapes) so that whenuseAssetsControlleris true the transaction-pay-controller can use a single action instead of five separate getState calls. Also exportformatStateForTransactionPayand typesTransactionPayLegacyFormat,AccountForLegacyFormat,LegacyTokenfrom utils (#8094)
- Bump
@metamask/assets-controllersfrom^100.0.3to^100.2.0(#8107), (#8140) - Bump
@metamask/network-enablement-controllerfrom^4.1.2to^4.2.0(#8107) - Bump
@metamask/transaction-controllerfrom^62.19.0to^62.21.0(#8104), (#8140) - Bump
@metamask/account-tree-controllerfrom^4.1.1to^5.0.0(#8140) - Bump
@metamask/core-backendfrom^6.0.0to^6.1.0(#8140) - Bump
@metamask/preferences-controllerfrom^22.1.0to^23.0.0(#8140)
formatExchangeRatesForBridgeandformatStateForTransactionPaynow read bothprice(selected currency) andusdPrice(USD) directly from asset price data (#8123)
- Add
getExchangeRatesForBridge()method andAssetsController:getExchangeRatesForBridgemessenger action. Returns bridge-compatible exchange rate state (conversionRates,currencyRates,marketData,currentCurrency) derived fromassetsPriceandselectedCurrency, for use when the bridge uses AssetsController for rates (#8076)
getExchangeRatesForBridge()/formatExchangeRatesForBridgereturn value:conversionRatesnow includes only non-EVM assets (EVM rates remain incurrencyRatesandmarketData); thecurrencyfield in conversionRates entries is resolved fromselectedCurrencyvia the same CAIP currency map as MultichainAssetsRatesController (no longer hardcoded); EVM entries inmarketDatanow include full price/market data (e.g.id,marketCap,allTimeHigh) in addition to bridge fields (#8076)
- Add
PendingTokenMetadatatype and optionalpendingMetadataparameter toaddCustomAsset(accountId, assetId, pendingMetadata?). When provided (e.g. from the extension's pending-tokens flow), token metadata is written toassetsInfoimmediately so the UI can render the token without waiting for the pipeline (#8021) - Add
currentCurrencystate (ISO 4217 code, default'usd') andsetCurrentCurrency(currentCurrency)toAssetsController. Changing the currency updates state and triggers a one-off price refetch so displayed prices use the new currency (#7991) - Add support for forcibly updating prices (#7991)
- Add parallel middlewares in
ParallelMiddleware.ts:createParallelBalanceMiddlewareruns balance data sources (Accounts API, Snap, RPC) in parallel with chain partitioning and a fallback round for failed chains;createParallelMiddlewareruns TokenDataSource and PriceDataSource in parallel (same request, merged response). Both usemergeDataResponsesand limited concurrency viap-limit(#7950) - Add
@metamask/client-controllerdependency and subscribe toClientController:stateChange. Asset tracking runs only when the UI is open (ClientController) and the keyring is unlocked (KeyringController), and stops when either the UI closes or the keyring locks (Client + Keyring lifecycle) (#7950) - Add full and merge update modes:
DataResponse.updateModeand typeAssetsUpdateMode('full'|'merge'). Fetch uses'full'(response is authoritative for scope; custom assets not in response are preserved). Subscriptions could use'merge'or'full'depending on data sources. Default is'merge'when omitted (#7950)
- Bump
@metamask/transaction-controllerfrom^62.17.1to^62.19.0(#8005, #8031) - Bump
@metamask/assets-controllersfrom^100.0.1to^100.0.2(#8004) - Bump
@metamask/assets-controllersfrom^100.0.2to^100.0.3(#8029)
- Avoid unnecessary price and token API requests when data sources report balance-only updates. The controller now forwards the optional
requestfrom the subscribe callback intohandleAssetsUpdate; when a data source callsonAssetsUpdate(response, request)withrequest.dataTypes: ['balance'](e.g. RpcDataSource balance polling, StakedBalanceDataSource), the controller skips Token and Price enrichment so the price API is not called. Previously every update triggered enrichment and could reset or overwrite existing state (#8043) - Default
assetsBalanceto0for native tokens of each account's supported chains usingNetworkEnablementController.nativeAssetIdentifiers, so native entries are always present in state even before data sources respond (#8036) - Auto-select
'merge'update mode ingetAssetswhenchainIdsis a subset of enabled chains, preventing partial-chain fetches (e.g. after a swap, adding a custom asset, or data-source chain changes) from wiping balances of other chains (#8036) - Convert WebSocket balance updates in
BackendWebsocketDataSourcefrom raw smallest-units to human-readable amounts using asset decimals (same behavior as RPC/Accounts API), soassetsBalanceremains consistent across data sources (#8032) - Include all assets from balance and each account's custom assets from state in
detectedAssets, so prices and metadata are fetched for existing assets and custom tokens (previously only assets without metadata were included, so existing assets did not get prices) (#8021) - Request
includeAggregators: truewhen fetching token metadata from the v3 assets API so aggregator data is returned and stored inassetsInfo(#8021)
- Bump
@metamask/assets-controllersfrom^100.0.0to^100.0.1(#7996) - Bump
@metamask/network-controllerfrom^29.0.0to^30.0.0(#7996) - Bump
@metamask/network-enablement-controllerfrom^4.1.1to^4.1.2(#7996) - Bump
@metamask/polling-controllerfrom^16.0.2to^16.0.3(#7996) - Bump
@metamask/transaction-controllerfrom^62.17.0to^62.17.1(#7996)
- Refactor data source tests to use shared
MockAssetControllerMessengerfixture (#7958)- Export
STAKING_INTERFACEfrom the staked balance fetcher for use with the staking contract ABI. StakedBalanceDataSourceteardown now uses the messenger'sclearEventSubscriptions; custom messenger implementations must support it for correct cleanup.
- Export
- Bump
@metamask/network-enablement-controllerfrom^4.1.0to^4.1.1(#7984) - Bump
@metamask/core-backendfrom^5.1.1to^6.0.0(#7993) - Bump
@metamask/assets-controllersfrom^99.4.0to^100.0.0(#7995) - Bump
@metamask/controller-utilsfrom^11.18.0to^11.19.0(#7995)
- Add
StakedBalanceDataSourcethat polls supported staking contracts on enabled chains and merges staked balances intoassetsBalance. Configurable viastakedBalanceDataSourceConfig(enabled,pollInterval); the controller subscribes to it when enabled and cleans up on destroy (#7936) - Add optional
trackMetaMetricsEventcallback to measure and report first init/fetch historical time (duration in ms) to MetaMetrics when the initial asset fetch completes after unlock or app open (#7871) - Add
AccountsApiDataSourceConfigandPriceDataSourceConfigtypes; addaccountsApiDataSourceConfigandpriceDataSourceConfigoptions toAssetsControllerOptionsfor per-data-source configuration (pollInterval, tokenDetectionEnabled, etc.). WhentokenDetectionEnabledis false,AccountsApiDataSourceonly returns balances for tokens already in state and does not add new tokens (#7926) - Add
useExternalServiceoption toTokenDetector,TokenDetectionOptions,RpcDataSourceConfig, andRpcDataSourceOptions. Token detection runs only when bothtokenDetectionEnabledanduseExternalServiceare true and stops when either is false (#7924) - Add basic functionality toggle:
isBasicFunctionality(getter() => boolean); no value is stored in the controller. When the getter returns true (matches UI "Basic functionality" ON), token and price APIs are used; when false, only RPC is used. OptionalsubscribeToBasicFunctionalityChange(onChange)lets the consumer register for toggle changes (e.g. extension subscribes to PreferencesController:stateChange, mobile uses its own mechanism); may return an unsubscribe function for controller destroy (#7904)
- Refactor
AssetsControllerMessengertype safety: removeas unknown ascasts, import types instead of locally defining them, and add missing allowed actions/events (#7952) - BREAKING:
AccountsApiDataSourceConfig.tokenDetectionEnabledis now a getter() => boolean(wasboolean) so the Accounts API data source reacts when the user toggles token detection at runtime, consistent withRpcDataSourceConfig.tokenDetectionEnabled. Pass a function, e.g.tokenDetectionEnabled: () => preferenceController.state.useTokenDetection. - BREAKING: Rename state and
DataResponseproperty fromassetsMetadatatoassetsInfo. Update consumers that readstate.assetsMetadataor setresponse.assetsMetadatato useassetsInfoinstead (#7902) - Bump
@metamask/keyring-apifrom^21.0.0to^21.5.0(#7857) - Bump
@metamask/keyring-internal-apifrom^9.0.0to^10.0.0(#7857) - Bump
@metamask/keyring-snap-clientfrom^8.0.0to^8.2.0(#7857) - Bump
@metamask/account-tree-controllerfrom4.1.0to4.1.1(#7897) - Bump
@metamask/core-backendfrom5.1.0to5.1.1(#7897)
- Add balance selectors
getAggregatedBalanceForAccount,getGroupIdForAccount, andgetInternalAccountsForGroupwith typesAggregatedBalanceEntry,AggregatedBalanceForAccount,EnabledNetworkMap, andAccountsByIdfor aggregated portfolio balance (optionally by account group), fiat total, and portfolio-weighted 1d price change (#7864)
- BREAKING: Require
previousChainsinhandleActiveChainsUpdate(dataSourceId, activeChains, previousChains)and in theonActiveChainsUpdatedcallback used by data sources; the third parameter is no longer optional. Callers and data sources must pass the previous chain list for correct added/removed chain diff computation (#7867) - Bump
@metamask/account-tree-controllerfrom^4.0.0to^4.1.0(#7869)
- BREAKING: Remove
initDataSourcesand related exports (InitDataSourcesOptions,DataSources,DataSourceActions,DataSourceEvents,DataSourceAllowedActions,DataSourceAllowedEvents,RootMessenger). Initialize assets by creatingAssetsControllerwithqueryApiClient; the controller instantiates all data sources internally (#7859)
- Add
assetPreferencesstate andAssetPreferencestype for per-asset UI preferences (e.g.hidden), separate fromassetsMetadata(#7777) - Add
hideAsset(assetId),unhideAsset(assetId)for managing hidden assets globally; hidden assets are excluded fromgetAssetsbut balance updates continue to be tracked (#7777)
-
Narrow
AssetsControllerStatetypes fromJsonto semantic types:assetsMetadata→AssetMetadata,assetsBalance→AssetBalance,assetsPrice→AssetPrice,assetPreferences→AssetPreferences,customAssets→Caip19AssetId[](#7777) -
Replace
viemdependency with@ethersproject/abifor ABI encoding/decoding inMulticallClient(#7839)
- Add
isEnabledoption toAssetsController,initMessengers, andinitDataSourcesto conditionally skip initialization when disabled and avoid duplicated requests (#7831) - Complete rewrite of AssetsController with middleware architecture for unified asset management across all blockchain networks (EVM and non-EVM) (#7685)
- Initial release (#7587)
- Add
MulticallClientfor batching RPC calls using Multicall3 contract (#7677) - Add batch utilities (
divideIntoBatches,reduceInBatchesSerially) for processing arrays in batches (#7677) - Add
TokenDetectorservice for detecting ERC-20 tokens with non-zero balances on a chain (#7683) - Add
BalanceFetcherservice for fetching token balances for user's imported/detected tokens (#7684) - Add configurable polling intervals for
RpcDataSourceviaRpcDataSourceConfigininitDataSources(#7709) - Add comprehensive unit tests for data sources (
AccountsApiDataSource,BackendWebsocketDataSource,PriceDataSource,TokenDataSource,SnapDataSource),DetectionMiddleware, andAssetsController(#7714)
- Bump
@metamask/core-backendfrom^5.0.0to^5.1.0(#7817) - Convert asset balances to human-readable format using token decimals across all data sources (
RpcDataSource,AccountsApiDataSource,BackendWebsocketDataSource) (#7752) - Store native token metadata (type, symbol, name, decimals) in
assetsMetadataderived fromNetworkControllerchain status (#7752) AccountsApiDataSourcenow includesassetsMetadatain response with token info from V5 API (#7752)- Bump
@metamask/keyring-controllerfrom^25.0.0to^25.1.0(#7713) - Refactor
RpcDataSourceto delegate polling toBalanceFetcherandTokenDetectorservices (#7709) - Refactor
BalanceFetcherandTokenDetectorto extendStaticIntervalPollingControllerOnlyfor independent polling management (#7709)