@metamask-previews/assets-controller 9.1.0-preview-e12e4a38f → 9.1.0-preview-4f9d41d
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 +8 -2
- package/dist/AssetsController.cjs +309 -136
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts +11 -8
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts +11 -8
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +309 -136
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.cjs +10 -0
- package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.cts +8 -0
- package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.mts +8 -0
- package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.mjs +10 -0
- package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.cjs +36 -60
- package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.cts +8 -0
- package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.mts +8 -0
- package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.mjs +36 -57
- package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
- package/dist/data-sources/PriceDataSource.cjs +18 -9
- package/dist/data-sources/PriceDataSource.cjs.map +1 -1
- package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
- package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
- package/dist/data-sources/PriceDataSource.mjs +19 -10
- package/dist/data-sources/PriceDataSource.mjs.map +1 -1
- package/dist/data-sources/RpcDataSource.cjs +29 -9
- package/dist/data-sources/RpcDataSource.cjs.map +1 -1
- package/dist/data-sources/RpcDataSource.d.cts +5 -0
- package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
- package/dist/data-sources/RpcDataSource.d.mts +5 -0
- package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
- package/dist/data-sources/RpcDataSource.mjs +29 -9
- package/dist/data-sources/RpcDataSource.mjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.cjs +22 -1
- package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.cts +3 -0
- package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.mts +3 -0
- package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.mjs +22 -1
- package/dist/middlewares/DetectionMiddleware.mjs.map +1 -1
- package/dist/middlewares/ParallelMiddleware.cjs +7 -0
- package/dist/middlewares/ParallelMiddleware.cjs.map +1 -1
- package/dist/middlewares/ParallelMiddleware.d.cts.map +1 -1
- package/dist/middlewares/ParallelMiddleware.d.mts.map +1 -1
- package/dist/middlewares/ParallelMiddleware.mjs +7 -0
- package/dist/middlewares/ParallelMiddleware.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +18 -9
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +18 -9
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/dedupingBatchFetcher.cjs +11 -0
- package/dist/utils/dedupingBatchFetcher.cjs.map +1 -1
- package/dist/utils/dedupingBatchFetcher.d.cts +7 -0
- package/dist/utils/dedupingBatchFetcher.d.cts.map +1 -1
- package/dist/utils/dedupingBatchFetcher.d.mts +7 -0
- package/dist/utils/dedupingBatchFetcher.d.mts.map +1 -1
- package/dist/utils/dedupingBatchFetcher.mjs +11 -0
- package/dist/utils/dedupingBatchFetcher.mjs.map +1 -1
- package/dist/utils/processAccountActivityBalanceUpdates.cjs +54 -0
- package/dist/utils/processAccountActivityBalanceUpdates.cjs.map +1 -0
- package/dist/utils/processAccountActivityBalanceUpdates.d.cts +13 -0
- package/dist/utils/processAccountActivityBalanceUpdates.d.cts.map +1 -0
- package/dist/utils/processAccountActivityBalanceUpdates.d.mts +13 -0
- package/dist/utils/processAccountActivityBalanceUpdates.d.mts.map +1 -0
- package/dist/utils/processAccountActivityBalanceUpdates.mjs +47 -0
- package/dist/utils/processAccountActivityBalanceUpdates.mjs.map +1 -0
- package/package.json +1 -1
|
@@ -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_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_captureException, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitTrace, _AssetsController_emitStateSizeTrace, _AssetsController_uiOpen, _AssetsController_keyringUnlocked, _AssetsController_controllerMutex, _AssetsController_accountRefreshMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_lastKnownAccountIds,
|
|
12
|
+
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_captureException, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitTrace, _AssetsController_emitStateSizeTrace, _AssetsController_uiOpen, _AssetsController_keyringUnlocked, _AssetsController_controllerMutex, _AssetsController_accountRefreshMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_lastKnownAccountIds, _AssetsController_getSelectedAccounts, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_customAssetGraduationMiddleware, _AssetsController_rpcFallbackMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_queryApiClient, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeNativeAssetsMap, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_onUnapprovedTransactionAdded, _AssetsController_onTransactionConfirmed, _AssetsController_onAccountActivityBalanceUpdated, _AssetsController_updateActive, _AssetsController_handleAccountTreeStateChange, _AssetsController_runAccountTreeRefresh, _AssetsController_runStartupRefresh, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_fetchMissingPricesWithoutCache, _AssetsController_getNativeAssetMap, _AssetsController_isNativeAsset, _AssetsController_getAssetType, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_getSlowPipelineChainIds, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_ensureDefaultTrackedAssetsSeeded, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_shouldHideNativeToken, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_subscribeRpcCustomAssetsSupplement, _AssetsController_unsubscribeBySubscriptionKey, _AssetsController_subscribeStakedBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged, _AssetsController_handleNetworkAdded, _AssetsController_refreshActiveChainsOnNetworkSwitch, _AssetsController_getSelectedEvmChainIdFromNetworkState, _AssetsController_handleNetworkDidChange, _AssetsController_refreshAssetsAfterNetworkChange, _AssetsController_refreshAssetsAfterNetworkAdded;
|
|
13
13
|
import { BaseController } from "@metamask/base-controller";
|
|
14
14
|
import { clientControllerSelectors } from "@metamask/client-controller";
|
|
15
15
|
import { isCaipChainId, isStrictHexString, KnownCaipNamespace, parseCaipAssetType, parseCaipChainId } from "@metamask/utils";
|
|
@@ -35,6 +35,7 @@ import { RpcFallbackMiddleware } from "./middlewares/RpcFallbackMiddleware.mjs";
|
|
|
35
35
|
import { normalizeAmountString, normalizeAssetId, formatExchangeRatesForBridge, formatStateForTransactionPay, buildNativeAssetsFromConstant, buildNativeAssetsFromApi } from "./utils/index.mjs";
|
|
36
36
|
import { ZERO_ADDRESS } from "./utils/constants.mjs";
|
|
37
37
|
import { pickRpcCustomAssetsSupplement } from "./utils/customAssetsRpcSupplement.mjs";
|
|
38
|
+
import { processAccountActivityBalanceUpdates } from "./utils/processAccountActivityBalanceUpdates.mjs";
|
|
38
39
|
const NATIVE_ASSETS_QUERY_KEY = ['nativeAssets'];
|
|
39
40
|
// ============================================================================
|
|
40
41
|
// CONTROLLER CONSTANTS
|
|
@@ -57,15 +58,6 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
57
58
|
];
|
|
58
59
|
/** Default polling interval hint for data sources (30 seconds) */
|
|
59
60
|
const DEFAULT_POLLING_INTERVAL_MS = 30000;
|
|
60
|
-
/** Sources whose passive polling must not overwrite recent websocket balances. */
|
|
61
|
-
const POLLING_BALANCE_SOURCES = new Set([
|
|
62
|
-
'AccountsApiDataSource',
|
|
63
|
-
'RpcDataSource',
|
|
64
|
-
'SnapDataSource',
|
|
65
|
-
'StakedBalanceDataSource',
|
|
66
|
-
]);
|
|
67
|
-
/** How long websocket balance updates block stale polling overwrites. */
|
|
68
|
-
const WS_BALANCE_FRESHNESS_MS = 120000;
|
|
69
61
|
// ============================================================================
|
|
70
62
|
// TRACE NAMES — used in Sentry spans (search these strings in Discover)
|
|
71
63
|
// ============================================================================
|
|
@@ -195,11 +187,41 @@ function normalizeResponse(response) {
|
|
|
195
187
|
if (response.updateMode) {
|
|
196
188
|
normalized.updateMode = response.updateMode;
|
|
197
189
|
}
|
|
198
|
-
if (response.
|
|
199
|
-
normalized.
|
|
190
|
+
if (response.replaceCoveredChainBalances) {
|
|
191
|
+
normalized.replaceCoveredChainBalances = true;
|
|
200
192
|
}
|
|
201
193
|
return normalized;
|
|
202
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Merge account balances from a data-source response into prior state.
|
|
197
|
+
*
|
|
198
|
+
* @param previousBalances - Balances already in state for this account.
|
|
199
|
+
* @param accountBalances - Balances from the incoming response.
|
|
200
|
+
* @param customAssetIds - Custom assets to preserve when replacing covered chains.
|
|
201
|
+
* @param replaceCoveredChains - When true, drop prior balances on chains present
|
|
202
|
+
* in the response before applying it (authoritative chain slice).
|
|
203
|
+
* @returns The merged balance map for the account.
|
|
204
|
+
*/
|
|
205
|
+
function mergeAccountBalances(previousBalances, accountBalances, customAssetIds, replaceCoveredChains) {
|
|
206
|
+
if (!replaceCoveredChains) {
|
|
207
|
+
return { ...previousBalances, ...accountBalances };
|
|
208
|
+
}
|
|
209
|
+
const coveredChains = new Set(Object.keys(accountBalances).map((assetId) => assetId.split('/')[0]));
|
|
210
|
+
const next = {};
|
|
211
|
+
for (const [assetId, balance] of Object.entries(previousBalances)) {
|
|
212
|
+
if (!coveredChains.has(assetId.split('/')[0])) {
|
|
213
|
+
next[assetId] = balance;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
Object.assign(next, accountBalances);
|
|
217
|
+
for (const customId of customAssetIds) {
|
|
218
|
+
if (!Object.prototype.hasOwnProperty.call(next, customId)) {
|
|
219
|
+
const prev = previousBalances[customId];
|
|
220
|
+
next[customId] = prev ?? { amount: '0' };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return next;
|
|
224
|
+
}
|
|
203
225
|
// ============================================================================
|
|
204
226
|
// CONTROLLER IMPLEMENTATION
|
|
205
227
|
// ============================================================================
|
|
@@ -278,11 +300,6 @@ export class AssetsController extends BaseController {
|
|
|
278
300
|
* re-subscriptions when the account set hasn't actually changed.
|
|
279
301
|
*/
|
|
280
302
|
_AssetsController_lastKnownAccountIds.set(this, new Set());
|
|
281
|
-
/**
|
|
282
|
-
* Per `accountId:assetId`, timestamp until which websocket balance updates
|
|
283
|
-
* should not be overwritten by polling/API fetches.
|
|
284
|
-
*/
|
|
285
|
-
_AssetsController_wsBalanceFreshUntil.set(this, new Map());
|
|
286
303
|
_AssetsController_backendWebsocketDataSource.set(this, void 0);
|
|
287
304
|
_AssetsController_accountsApiDataSource.set(this, void 0);
|
|
288
305
|
_AssetsController_snapDataSource.set(this, void 0);
|
|
@@ -431,9 +448,9 @@ export class AssetsController extends BaseController {
|
|
|
431
448
|
// creation, RPC is slow on many chains). Results are committed to state
|
|
432
449
|
// immediately so the UI can display balances without waiting for them.
|
|
433
450
|
//
|
|
434
|
-
//
|
|
435
|
-
//
|
|
436
|
-
//
|
|
451
|
+
// Fast/slow pipelines use merge so partial API snapshots cannot wipe
|
|
452
|
+
// tokens missing from the response (e.g. USDC when only native balance
|
|
453
|
+
// is returned). Balances present in the response are still refreshed.
|
|
437
454
|
const fastSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
438
455
|
? [
|
|
439
456
|
createParallelBalanceMiddleware([
|
|
@@ -453,39 +470,36 @@ export class AssetsController extends BaseController {
|
|
|
453
470
|
]
|
|
454
471
|
: [__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f")];
|
|
455
472
|
const { response, durationByDataSource } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, fastSources, request);
|
|
456
|
-
// The fast pipeline only contains a subset of data sources (AccountsApi +
|
|
457
|
-
// StakedBalance), so it must always merge to avoid wiping Snap/RPC
|
|
458
|
-
// balances that the background pipeline hasn't yet replaced.
|
|
459
473
|
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
460
474
|
...response,
|
|
461
475
|
updateMode: 'merge',
|
|
462
|
-
|
|
476
|
+
replaceCoveredChainBalances: true,
|
|
463
477
|
});
|
|
464
478
|
// Background pipeline: snap and RPC run in parallel after the fast path
|
|
465
479
|
// commits to state. Their balances are merged together before detection.
|
|
466
480
|
// Token + price enrichment matches the pre-split behavior: only when basic
|
|
467
481
|
// functionality is on (RPC-only mode must not call token/price APIs).
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
482
|
+
const slowPipelineChainIds = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSlowPipelineChainIds).call(this, chainIds, response);
|
|
483
|
+
if (slowPipelineChainIds.length > 0) {
|
|
484
|
+
const slowSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
485
|
+
? [__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")]
|
|
486
|
+
: [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
|
|
487
|
+
const slowRequest = { ...request, chainIds: slowPipelineChainIds };
|
|
488
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, [
|
|
489
|
+
createParallelBalanceMiddleware(slowSources),
|
|
490
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
|
|
491
|
+
...(__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
492
|
+
? [
|
|
493
|
+
createParallelMiddleware([
|
|
494
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
|
|
495
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
|
|
496
|
+
]),
|
|
497
|
+
]
|
|
498
|
+
: []),
|
|
499
|
+
], slowRequest)
|
|
500
|
+
.then(({ response: slowResponse }) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, { ...slowResponse, updateMode: 'merge' }))
|
|
501
|
+
.catch((error) => log('Background pipeline failed', { error }));
|
|
502
|
+
}
|
|
489
503
|
const durationMs = performance.now() - startTime;
|
|
490
504
|
// Emit trace for every full fetch (Assets Health dashboard)
|
|
491
505
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_FULL_FETCH, {
|
|
@@ -877,7 +891,8 @@ export class AssetsController extends BaseController {
|
|
|
877
891
|
// RPC already fetches custom assets on purpose, and Snap handles non-EVM
|
|
878
892
|
// chains the rule does not apply to, so skip the middleware for those.
|
|
879
893
|
const shouldGraduateCustomAssets = sourceId === 'AccountsApiDataSource' ||
|
|
880
|
-
sourceId === 'BackendWebsocketDataSource'
|
|
894
|
+
sourceId === 'BackendWebsocketDataSource' ||
|
|
895
|
+
sourceId === 'AccountActivityService';
|
|
881
896
|
const enrichmentSources = [
|
|
882
897
|
...(shouldGraduateCustomAssets
|
|
883
898
|
? [__classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f")]
|
|
@@ -891,11 +906,10 @@ export class AssetsController extends BaseController {
|
|
|
891
906
|
]));
|
|
892
907
|
}
|
|
893
908
|
const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, enrichmentSources, pipelineRequest, response);
|
|
894
|
-
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
}
|
|
909
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
910
|
+
...enrichedResponse,
|
|
911
|
+
replaceCoveredChainBalances: response.replaceCoveredChainBalances,
|
|
912
|
+
});
|
|
899
913
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_UPDATE_PIPELINE, {
|
|
900
914
|
source: sourceId,
|
|
901
915
|
duration_ms: performance.now() - updateStart,
|
|
@@ -942,7 +956,7 @@ export class AssetsController extends BaseController {
|
|
|
942
956
|
this.messenger.unregisterActionHandler('AssetsController:setSelectedCurrency');
|
|
943
957
|
}
|
|
944
958
|
}
|
|
945
|
-
_AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_captureException = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_stateSizeReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_accountRefreshMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_lastKnownAccountIds = new WeakMap(),
|
|
959
|
+
_AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_captureException = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_stateSizeReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_accountRefreshMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_lastKnownAccountIds = new WeakMap(), _AssetsController_backendWebsocketDataSource = new WeakMap(), _AssetsController_accountsApiDataSource = new WeakMap(), _AssetsController_snapDataSource = new WeakMap(), _AssetsController_rpcDataSource = new WeakMap(), _AssetsController_stakedBalanceDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_customAssetGraduationMiddleware = new WeakMap(), _AssetsController_rpcFallbackMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_queryApiClient = new WeakMap(), _AssetsController_onActiveChainsUpdated = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_emitTrace = function _AssetsController_emitTrace(name, data, tags = {
|
|
946
960
|
controller: 'AssetsController',
|
|
947
961
|
}) {
|
|
948
962
|
if (!__classPrivateFieldGet(this, _AssetsController_trace, "f")) {
|
|
@@ -1068,11 +1082,11 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1068
1082
|
// The base-controller `:stateChange` event is guaranteed to fire
|
|
1069
1083
|
// when init() calls this.update(). #start() is idempotent so
|
|
1070
1084
|
// repeated fires are safe.
|
|
1071
|
-
this.messenger.subscribe('AccountTreeController:
|
|
1085
|
+
this.messenger.subscribe('AccountTreeController:stateChanged', () => {
|
|
1072
1086
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleAccountTreeStateChange).call(this);
|
|
1073
1087
|
});
|
|
1074
1088
|
// Subscribe to network enablement changes (only enabledNetworkMap)
|
|
1075
|
-
this.messenger.subscribe('NetworkEnablementController:
|
|
1089
|
+
this.messenger.subscribe('NetworkEnablementController:stateChanged', ({ enabledNetworkMap }) => {
|
|
1076
1090
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleEnabledNetworksChanged).call(this, enabledNetworkMap).catch(console.error);
|
|
1077
1091
|
});
|
|
1078
1092
|
// When a network is added or removed from NetworkController, refresh
|
|
@@ -1083,13 +1097,20 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1083
1097
|
// enabled in NetworkEnablementController.
|
|
1084
1098
|
this.messenger.subscribe('NetworkController:networkAdded', (networkConfiguration) => {
|
|
1085
1099
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleNetworkAdded).call(this, networkConfiguration.chainId);
|
|
1086
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
1100
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_refreshAssetsAfterNetworkAdded).call(this, networkConfiguration.chainId).catch((error) => {
|
|
1101
|
+
log('Failed to refresh assets after network added', { error });
|
|
1102
|
+
});
|
|
1087
1103
|
});
|
|
1088
1104
|
this.messenger.subscribe('NetworkController:networkRemoved', () => {
|
|
1089
1105
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_refreshAssetsAfterNetworkChange).call(this);
|
|
1090
1106
|
});
|
|
1107
|
+
// Selected EVM network switch (network picker). Enablement changes are
|
|
1108
|
+
// handled separately via NetworkEnablementController:stateChanged.
|
|
1109
|
+
this.messenger.subscribe('NetworkController:networkDidChange', (networkState) => {
|
|
1110
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleNetworkDidChange).call(this, networkState).catch(console.error);
|
|
1111
|
+
});
|
|
1091
1112
|
// Client + Keyring lifecycle: only run when UI is open AND keyring is unlocked
|
|
1092
|
-
this.messenger.subscribe('ClientController:
|
|
1113
|
+
this.messenger.subscribe('ClientController:stateChanged', (isUiOpen) => {
|
|
1093
1114
|
__classPrivateFieldSet(this, _AssetsController_uiOpen, isUiOpen, "f");
|
|
1094
1115
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateActive).call(this);
|
|
1095
1116
|
}, clientControllerSelectors.selectIsUiOpen);
|
|
@@ -1106,6 +1127,18 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1106
1127
|
this.messenger.subscribe('TransactionController:unapprovedTransactionAdded', (transactionMeta) => {
|
|
1107
1128
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_onUnapprovedTransactionAdded).call(this, transactionMeta);
|
|
1108
1129
|
});
|
|
1130
|
+
// Post-tx refresh via the full fetch pipeline (Accounts API + RPC fallback).
|
|
1131
|
+
// RpcDataSource also listens for transactionConfirmed, but only refreshes
|
|
1132
|
+
// chains it owns via an active subscription.
|
|
1133
|
+
this.messenger.subscribe('TransactionController:transactionConfirmed', (transactionMeta) => {
|
|
1134
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_onTransactionConfirmed).call(this, transactionMeta);
|
|
1135
|
+
});
|
|
1136
|
+
// Real-time post-tx balances from AccountActivityService (same WS payload as
|
|
1137
|
+
// TokenBalancesController; BackendWebsocketDataSource may not receive the
|
|
1138
|
+
// callback when AccountActivityService owns the server subscription).
|
|
1139
|
+
this.messenger.subscribe('AccountActivityService:balanceUpdated', (event) => {
|
|
1140
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_onAccountActivityBalanceUpdated).call(this, event);
|
|
1141
|
+
});
|
|
1109
1142
|
}, _AssetsController_onUnapprovedTransactionAdded = function _AssetsController_onUnapprovedTransactionAdded(transactionMeta) {
|
|
1110
1143
|
const hexChainId = transactionMeta.chainId;
|
|
1111
1144
|
if (!hexChainId) {
|
|
@@ -1128,6 +1161,46 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1128
1161
|
error,
|
|
1129
1162
|
});
|
|
1130
1163
|
});
|
|
1164
|
+
}, _AssetsController_onTransactionConfirmed = function _AssetsController_onTransactionConfirmed(transactionMeta) {
|
|
1165
|
+
const hexChainId = transactionMeta.chainId;
|
|
1166
|
+
if (!hexChainId) {
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const caipChainId = `eip155:${parseInt(hexChainId, 16)}`;
|
|
1170
|
+
const fromAddress = transactionMeta.txParams.from?.toLowerCase();
|
|
1171
|
+
if (!fromAddress) {
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
const matchedAccount = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((account) => account.address.toLowerCase() === fromAddress);
|
|
1175
|
+
if (!matchedAccount) {
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
this.getAssets([matchedAccount], {
|
|
1179
|
+
chainIds: [caipChainId],
|
|
1180
|
+
forceUpdate: true,
|
|
1181
|
+
}).catch((error) => {
|
|
1182
|
+
log('Failed to refresh assets after transaction confirmed', { error });
|
|
1183
|
+
});
|
|
1184
|
+
}, _AssetsController_onAccountActivityBalanceUpdated = function _AssetsController_onAccountActivityBalanceUpdated({ address, chain, updates, }) {
|
|
1185
|
+
const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.address.startsWith('0x')
|
|
1186
|
+
? a.address.toLowerCase() === address.toLowerCase()
|
|
1187
|
+
: a.address === address);
|
|
1188
|
+
if (!account) {
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1191
|
+
const chainId = chain;
|
|
1192
|
+
const response = processAccountActivityBalanceUpdates(updates, account.id, (assetId) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetType).call(this, assetId));
|
|
1193
|
+
if (!response.assetsBalance) {
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
const request = {
|
|
1197
|
+
accountsWithSupportedChains: [{ account, supportedChains: [chainId] }],
|
|
1198
|
+
chainIds: [chainId],
|
|
1199
|
+
dataTypes: ['balance', 'metadata'],
|
|
1200
|
+
};
|
|
1201
|
+
this.handleAssetsUpdate(response, 'AccountActivityService', request).catch((error) => {
|
|
1202
|
+
log('Failed to apply AccountActivityService balance update', { error });
|
|
1203
|
+
});
|
|
1131
1204
|
}, _AssetsController_updateActive = function _AssetsController_updateActive() {
|
|
1132
1205
|
const shouldRun = __classPrivateFieldGet(this, _AssetsController_uiOpen, "f") && __classPrivateFieldGet(this, _AssetsController_keyringUnlocked, "f");
|
|
1133
1206
|
if (shouldRun) {
|
|
@@ -1183,6 +1256,32 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1183
1256
|
finally {
|
|
1184
1257
|
releaseLock();
|
|
1185
1258
|
}
|
|
1259
|
+
}, _AssetsController_runStartupRefresh =
|
|
1260
|
+
/**
|
|
1261
|
+
* Force-fetch balances then subscribe. Used on unlock / first startup.
|
|
1262
|
+
*
|
|
1263
|
+
* @param accounts - Selected accounts to refresh.
|
|
1264
|
+
*/
|
|
1265
|
+
async function _AssetsController_runStartupRefresh(accounts) {
|
|
1266
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_accountRefreshMutex, "f").acquire();
|
|
1267
|
+
try {
|
|
1268
|
+
await this.getAssets(accounts, {
|
|
1269
|
+
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
1270
|
+
forceUpdate: true,
|
|
1271
|
+
});
|
|
1272
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1273
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
1274
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1275
|
+
}
|
|
1276
|
+
catch (error) {
|
|
1277
|
+
log('Failed to fetch assets on startup', error);
|
|
1278
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1279
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
1280
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1281
|
+
}
|
|
1282
|
+
finally {
|
|
1283
|
+
releaseLock();
|
|
1284
|
+
}
|
|
1186
1285
|
}, _AssetsController_registerActionHandlers = function _AssetsController_registerActionHandlers() {
|
|
1187
1286
|
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
1188
1287
|
}, _AssetsController_handleActiveChainsUpdate = function _AssetsController_handleActiveChainsUpdate(dataSourceId, activeChains, previousChains) {
|
|
@@ -1296,6 +1395,41 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1296
1395
|
});
|
|
1297
1396
|
}
|
|
1298
1397
|
return { response: result.response, durationByDataSource };
|
|
1398
|
+
}, _AssetsController_fetchMissingPricesWithoutCache = function _AssetsController_fetchMissingPricesWithoutCache(accounts, chainIds) {
|
|
1399
|
+
if (!__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this) || accounts.length === 0) {
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
const accountIds = new Set(accounts.map((account) => account.id));
|
|
1403
|
+
const chainFilter = new Set(chainIds);
|
|
1404
|
+
const assetsForPriceUpdate = [];
|
|
1405
|
+
const prices = this.state.assetsPrice;
|
|
1406
|
+
for (const [accountId, accountBalances] of Object.entries(this.state.assetsBalance)) {
|
|
1407
|
+
if (!accountIds.has(accountId)) {
|
|
1408
|
+
continue;
|
|
1409
|
+
}
|
|
1410
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
1411
|
+
if (!chainFilter.has(assetId.split('/')[0])) {
|
|
1412
|
+
continue;
|
|
1413
|
+
}
|
|
1414
|
+
const normalizedAssetId = normalizeAssetId(assetId);
|
|
1415
|
+
if (prices[normalizedAssetId] ?? prices[assetId]) {
|
|
1416
|
+
continue;
|
|
1417
|
+
}
|
|
1418
|
+
assetsForPriceUpdate.push(normalizedAssetId);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
if (assetsForPriceUpdate.length === 0) {
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").invalidatePriceCache();
|
|
1425
|
+
this.getAssets(accounts, {
|
|
1426
|
+
forceUpdate: true,
|
|
1427
|
+
dataTypes: ['price'],
|
|
1428
|
+
chainIds,
|
|
1429
|
+
assetsForPriceUpdate,
|
|
1430
|
+
}).catch((error) => {
|
|
1431
|
+
log('Failed to fetch missing prices', { error });
|
|
1432
|
+
});
|
|
1299
1433
|
}, _AssetsController_getNativeAssetMap = function _AssetsController_getNativeAssetMap() {
|
|
1300
1434
|
return (__classPrivateFieldGet(this, _AssetsController_queryApiClient, "f").getCachedData(NATIVE_ASSETS_QUERY_KEY) ?? {});
|
|
1301
1435
|
}, _AssetsController_isNativeAsset = function _AssetsController_isNativeAsset(assetId) {
|
|
@@ -1337,6 +1471,17 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1337
1471
|
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_resolveNativeAssetIds).call(this, __classPrivateFieldGet(this, _AssetsController_enabledChains, "f"));
|
|
1338
1472
|
}, _AssetsController_getNativeAssetIdsForAccount = function _AssetsController_getNativeAssetIdsForAccount(account) {
|
|
1339
1473
|
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_resolveNativeAssetIds).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account));
|
|
1474
|
+
}, _AssetsController_getSlowPipelineChainIds = function _AssetsController_getSlowPipelineChainIds(chainIds, fastResponse) {
|
|
1475
|
+
const accountsApiChains = new Set(__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f").getActiveChainsSync());
|
|
1476
|
+
return chainIds.filter((chainId) => {
|
|
1477
|
+
if (fastResponse.errors?.[chainId]) {
|
|
1478
|
+
return true;
|
|
1479
|
+
}
|
|
1480
|
+
if (!accountsApiChains.has(chainId)) {
|
|
1481
|
+
return true;
|
|
1482
|
+
}
|
|
1483
|
+
return false;
|
|
1484
|
+
});
|
|
1340
1485
|
}, _AssetsController_ensureNativeBalancesDefaultZero = function _AssetsController_ensureNativeBalancesDefaultZero() {
|
|
1341
1486
|
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
1342
1487
|
if (accounts.length === 0) {
|
|
@@ -1354,7 +1499,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1354
1499
|
balances[accountId] = {};
|
|
1355
1500
|
}
|
|
1356
1501
|
for (const nativeAssetId of nativeAssetIds) {
|
|
1357
|
-
if (!(
|
|
1502
|
+
if (!Object.prototype.hasOwnProperty.call(balances[accountId], nativeAssetId)) {
|
|
1358
1503
|
balances[accountId][nativeAssetId] = { amount: '0' };
|
|
1359
1504
|
}
|
|
1360
1505
|
}
|
|
@@ -1404,37 +1549,9 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1404
1549
|
}
|
|
1405
1550
|
}
|
|
1406
1551
|
});
|
|
1407
|
-
}, _AssetsController_filterBalancesRespectingWsFreshness = function _AssetsController_filterBalancesRespectingWsFreshness(accountId, accountBalances, sourceId) {
|
|
1408
|
-
if (!sourceId || !POLLING_BALANCE_SOURCES.has(sourceId)) {
|
|
1409
|
-
return accountBalances;
|
|
1410
|
-
}
|
|
1411
|
-
const now = Date.now();
|
|
1412
|
-
const filtered = {};
|
|
1413
|
-
for (const [assetId, balance] of Object.entries(accountBalances)) {
|
|
1414
|
-
const freshUntil = __classPrivateFieldGet(this, _AssetsController_wsBalanceFreshUntil, "f").get(`${accountId}:${assetId}`);
|
|
1415
|
-
if (freshUntil !== undefined && now < freshUntil) {
|
|
1416
|
-
continue;
|
|
1417
|
-
}
|
|
1418
|
-
filtered[assetId] = balance;
|
|
1419
|
-
}
|
|
1420
|
-
return filtered;
|
|
1421
|
-
}, _AssetsController_markWsBalancesFresh = function _AssetsController_markWsBalancesFresh(assetsBalance) {
|
|
1422
|
-
const freshUntil = Date.now() + WS_BALANCE_FRESHNESS_MS;
|
|
1423
|
-
for (const [accountId, balances] of Object.entries(assetsBalance)) {
|
|
1424
|
-
for (const assetId of Object.keys(balances)) {
|
|
1425
|
-
__classPrivateFieldGet(this, _AssetsController_wsBalanceFreshUntil, "f").set(`${accountId}:${assetId}`, freshUntil);
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
}, _AssetsController_clearWsBalanceFreshness = function _AssetsController_clearWsBalanceFreshness(assetsBalance) {
|
|
1429
|
-
for (const [accountId, balances] of Object.entries(assetsBalance)) {
|
|
1430
|
-
for (const assetId of Object.keys(balances)) {
|
|
1431
|
-
__classPrivateFieldGet(this, _AssetsController_wsBalanceFreshUntil, "f").delete(`${accountId}:${assetId}`);
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
1552
|
}, _AssetsController_updateState = async function _AssetsController_updateState(response) {
|
|
1435
1553
|
const normalizedResponse = normalizeResponse(response);
|
|
1436
1554
|
const mode = normalizedResponse.updateMode ?? 'merge';
|
|
1437
|
-
const assetsBalanceToApply = normalizedResponse.assetsBalance;
|
|
1438
1555
|
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_controllerMutex, "f").acquire();
|
|
1439
1556
|
try {
|
|
1440
1557
|
const previousState = this.state;
|
|
@@ -1495,48 +1612,20 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1495
1612
|
}
|
|
1496
1613
|
}
|
|
1497
1614
|
}
|
|
1498
|
-
if (
|
|
1499
|
-
for (const [accountId, accountBalances] of Object.entries(
|
|
1500
|
-
const filteredAccountBalances = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_filterBalancesRespectingWsFreshness).call(this, accountId, accountBalances, normalizedResponse.sourceId);
|
|
1615
|
+
if (normalizedResponse.assetsBalance) {
|
|
1616
|
+
for (const [accountId, accountBalances] of Object.entries(normalizedResponse.assetsBalance)) {
|
|
1501
1617
|
const previousBalances = previousState.assetsBalance[accountId] ?? {};
|
|
1502
1618
|
const customAssetIds = state.customAssets[accountId] ?? [];
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
// are never inadvertently reset to zero.
|
|
1507
|
-
// Merge: response overlays previous balances.
|
|
1508
|
-
const effective = mode === 'merge'
|
|
1509
|
-
? { ...previousBalances, ...filteredAccountBalances }
|
|
1510
|
-
: (() => {
|
|
1511
|
-
// Determine which chain namespaces this response covers.
|
|
1512
|
-
const coveredChains = new Set(Object.keys(filteredAccountBalances).map((assetId) => assetId.split('/')[0]));
|
|
1513
|
-
// Start from previous balances, dropping only entries for
|
|
1514
|
-
// chains this response is authoritative over.
|
|
1515
|
-
const next = {};
|
|
1516
|
-
for (const [assetId, balance] of Object.entries(previousBalances)) {
|
|
1517
|
-
if (!coveredChains.has(assetId.split('/')[0])) {
|
|
1518
|
-
next[assetId] = balance;
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
// Apply the response (authoritative for covered chains).
|
|
1522
|
-
Object.assign(next, filteredAccountBalances);
|
|
1523
|
-
// Preserve custom assets that the response omitted.
|
|
1524
|
-
for (const customId of customAssetIds) {
|
|
1525
|
-
if (!(customId in next)) {
|
|
1526
|
-
const prev = previousBalances[customId];
|
|
1527
|
-
next[customId] =
|
|
1528
|
-
prev ?? { amount: '0' };
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
return next;
|
|
1532
|
-
})();
|
|
1619
|
+
const replaceCoveredChains = mode === 'full' ||
|
|
1620
|
+
normalizedResponse.replaceCoveredChainBalances === true;
|
|
1621
|
+
const effective = mergeAccountBalances(previousBalances, accountBalances, customAssetIds, replaceCoveredChains);
|
|
1533
1622
|
// Ensure native tokens have an entry (0 if missing) for chains this account supports
|
|
1534
1623
|
const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.id === accountId);
|
|
1535
1624
|
const nativeAssetIdsForAccount = account
|
|
1536
1625
|
? __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForAccount).call(this, account)
|
|
1537
1626
|
: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForEnabledChains).call(this);
|
|
1538
1627
|
for (const nativeAssetId of nativeAssetIdsForAccount) {
|
|
1539
|
-
if (!(nativeAssetId
|
|
1628
|
+
if (!Object.prototype.hasOwnProperty.call(effective, nativeAssetId)) {
|
|
1540
1629
|
effective[nativeAssetId] = { amount: '0' };
|
|
1541
1630
|
}
|
|
1542
1631
|
}
|
|
@@ -1568,7 +1657,6 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1568
1657
|
balances[accountId] = effective;
|
|
1569
1658
|
}
|
|
1570
1659
|
}
|
|
1571
|
-
// Update prices in state
|
|
1572
1660
|
if (normalizedResponse.assetsPrice) {
|
|
1573
1661
|
for (const [key, value] of Object.entries(normalizedResponse.assetsPrice)) {
|
|
1574
1662
|
prices[key] = value;
|
|
@@ -1631,12 +1719,6 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1631
1719
|
});
|
|
1632
1720
|
}
|
|
1633
1721
|
}
|
|
1634
|
-
// Authoritative fetch on account switch — drop WS freshness locks so API
|
|
1635
|
-
// balances (e.g. receiver +1 USDC) replace stale values from a prior send.
|
|
1636
|
-
if (normalizedResponse.sourceId === 'getAssets:forceUpdate' &&
|
|
1637
|
-
assetsBalanceToApply) {
|
|
1638
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_clearWsBalanceFreshness).call(this, assetsBalanceToApply);
|
|
1639
|
-
}
|
|
1640
1722
|
}
|
|
1641
1723
|
finally {
|
|
1642
1724
|
releaseLock();
|
|
@@ -1735,14 +1817,8 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1735
1817
|
enabledChainCount: chainIds.length,
|
|
1736
1818
|
});
|
|
1737
1819
|
__classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(accounts.map((a) => a.id)), "f");
|
|
1738
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
1739
|
-
|
|
1740
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1741
|
-
this.getAssets(accounts, {
|
|
1742
|
-
chainIds,
|
|
1743
|
-
forceUpdate: true,
|
|
1744
|
-
}).catch((error) => {
|
|
1745
|
-
log('Failed to fetch assets', error);
|
|
1820
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_runStartupRefresh).call(this, accounts).catch((error) => {
|
|
1821
|
+
log('Failed to start asset tracking', error);
|
|
1746
1822
|
});
|
|
1747
1823
|
}, _AssetsController_stop = function _AssetsController_stop() {
|
|
1748
1824
|
log('Stopping asset tracking', {
|
|
@@ -1820,7 +1896,13 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1820
1896
|
const seenIds = new Set();
|
|
1821
1897
|
const accountsForSource = assignedChains
|
|
1822
1898
|
.flatMap((chainId) => chainToAccounts.get(chainId) ?? [])
|
|
1823
|
-
.filter((account) =>
|
|
1899
|
+
.filter((account) => {
|
|
1900
|
+
if (seenIds.has(account.id)) {
|
|
1901
|
+
return false;
|
|
1902
|
+
}
|
|
1903
|
+
seenIds.add(account.id);
|
|
1904
|
+
return true;
|
|
1905
|
+
});
|
|
1824
1906
|
if (accountsForSource.length > 0) {
|
|
1825
1907
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accountsForSource, assignedChains);
|
|
1826
1908
|
}
|
|
@@ -2082,11 +2164,102 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
2082
2164
|
caipChainId,
|
|
2083
2165
|
});
|
|
2084
2166
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this, [caipChainId]);
|
|
2167
|
+
}, _AssetsController_refreshActiveChainsOnNetworkSwitch =
|
|
2168
|
+
/**
|
|
2169
|
+
* Refresh data-source `activeChains` after an EVM network switch so API/WS/Rpc
|
|
2170
|
+
* chain claiming is not stuck on an empty or stale init-time list.
|
|
2171
|
+
*/
|
|
2172
|
+
async function _AssetsController_refreshActiveChainsOnNetworkSwitch() {
|
|
2173
|
+
await Promise.all([
|
|
2174
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f").refreshActiveChains(),
|
|
2175
|
+
__classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f").refreshActiveChains(),
|
|
2176
|
+
]);
|
|
2177
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f").refreshActiveChainsFromNetworkState();
|
|
2178
|
+
}, _AssetsController_getSelectedEvmChainIdFromNetworkState = function _AssetsController_getSelectedEvmChainIdFromNetworkState(networkState) {
|
|
2179
|
+
try {
|
|
2180
|
+
const networkClient = this.messenger.call('NetworkController:getNetworkClientById', networkState.selectedNetworkClientId);
|
|
2181
|
+
const hexChainId = networkClient.configuration?.chainId;
|
|
2182
|
+
if (!hexChainId) {
|
|
2183
|
+
return undefined;
|
|
2184
|
+
}
|
|
2185
|
+
return `eip155:${parseInt(hexChainId, 16)}`;
|
|
2186
|
+
}
|
|
2187
|
+
catch {
|
|
2188
|
+
return undefined;
|
|
2189
|
+
}
|
|
2190
|
+
}, _AssetsController_handleNetworkDidChange =
|
|
2191
|
+
/**
|
|
2192
|
+
* Refresh subscriptions and fetch balances when the user switches the
|
|
2193
|
+
* selected EVM network in the UI (`NetworkController:networkDidChange`).
|
|
2194
|
+
*
|
|
2195
|
+
* @param networkState - NetworkController state after the switch.
|
|
2196
|
+
*/
|
|
2197
|
+
async function _AssetsController_handleNetworkDidChange(networkState) {
|
|
2198
|
+
if (!__classPrivateFieldGet(this, _AssetsController_uiOpen, "f") || !__classPrivateFieldGet(this, _AssetsController_keyringUnlocked, "f") || !__classPrivateFieldGet(this, _AssetsController_isEnabled, "f").call(this)) {
|
|
2199
|
+
return;
|
|
2200
|
+
}
|
|
2201
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2202
|
+
if (accounts.length === 0) {
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
const selectedChainId = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedEvmChainIdFromNetworkState).call(this, networkState);
|
|
2206
|
+
if (!selectedChainId) {
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
log('Selected EVM network switched', {
|
|
2210
|
+
selectedNetworkClientId: networkState.selectedNetworkClientId,
|
|
2211
|
+
selectedChainId,
|
|
2212
|
+
});
|
|
2213
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_accountRefreshMutex, "f").acquire();
|
|
2214
|
+
try {
|
|
2215
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_refreshActiveChainsOnNetworkSwitch).call(this);
|
|
2216
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
2217
|
+
await this.getAssets(accounts, {
|
|
2218
|
+
chainIds: [selectedChainId],
|
|
2219
|
+
forceUpdate: true,
|
|
2220
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
2221
|
+
});
|
|
2222
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
2223
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [selectedChainId]);
|
|
2224
|
+
}
|
|
2225
|
+
finally {
|
|
2226
|
+
releaseLock();
|
|
2227
|
+
}
|
|
2085
2228
|
}, _AssetsController_refreshAssetsAfterNetworkChange = function _AssetsController_refreshAssetsAfterNetworkChange() {
|
|
2086
|
-
|
|
2229
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2230
|
+
if (accounts.length === 0) {
|
|
2231
|
+
return;
|
|
2232
|
+
}
|
|
2233
|
+
this.getAssets(accounts, {
|
|
2087
2234
|
forceUpdate: true,
|
|
2235
|
+
dataTypes: ['balance', 'metadata'],
|
|
2088
2236
|
}).catch((error) => {
|
|
2089
2237
|
log('Failed to refresh assets after network change', { error });
|
|
2090
2238
|
});
|
|
2239
|
+
}, _AssetsController_refreshAssetsAfterNetworkAdded =
|
|
2240
|
+
/**
|
|
2241
|
+
* Refresh balances and fetch missing prices after a network is added.
|
|
2242
|
+
*
|
|
2243
|
+
* @param hexChainId - Hex chain id of the newly-added network.
|
|
2244
|
+
*/
|
|
2245
|
+
async function _AssetsController_refreshAssetsAfterNetworkAdded(hexChainId) {
|
|
2246
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2247
|
+
if (accounts.length === 0) {
|
|
2248
|
+
return;
|
|
2249
|
+
}
|
|
2250
|
+
let caipChainId;
|
|
2251
|
+
try {
|
|
2252
|
+
caipChainId = `eip155:${parseInt(hexChainId, 16)}`;
|
|
2253
|
+
}
|
|
2254
|
+
catch {
|
|
2255
|
+
return;
|
|
2256
|
+
}
|
|
2257
|
+
await this.getAssets(accounts, {
|
|
2258
|
+
chainIds: [caipChainId],
|
|
2259
|
+
forceUpdate: true,
|
|
2260
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
2261
|
+
});
|
|
2262
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
2263
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [caipChainId]);
|
|
2091
2264
|
};
|
|
2092
2265
|
//# sourceMappingURL=AssetsController.mjs.map
|