@metamask/assets-controller 9.0.2 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -1
- package/dist/AssetsController.cjs +357 -105
- 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 +357 -105
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.cjs +15 -2
- 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 +15 -2
- package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.cjs +236 -149
- package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.cts +15 -0
- package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.mts +15 -0
- package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.mjs +236 -146
- package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
- package/dist/data-sources/PriceDataSource.cjs +82 -22
- package/dist/data-sources/PriceDataSource.cjs.map +1 -1
- package/dist/data-sources/PriceDataSource.d.cts +13 -0
- package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
- package/dist/data-sources/PriceDataSource.d.mts +13 -0
- package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
- package/dist/data-sources/PriceDataSource.mjs +83 -23
- 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/data-sources/SnapDataSource.cjs +2 -2
- package/dist/data-sources/SnapDataSource.cjs.map +1 -1
- package/dist/data-sources/SnapDataSource.mjs +2 -2
- package/dist/data-sources/SnapDataSource.mjs.map +1 -1
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.cjs +64 -23
- package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.cts +15 -13
- package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.mts +15 -13
- package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.mjs +64 -23
- 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/selectors/balance.cjs +191 -8
- package/dist/selectors/balance.cjs.map +1 -1
- package/dist/selectors/balance.d.cts +80 -0
- package/dist/selectors/balance.d.cts.map +1 -1
- package/dist/selectors/balance.d.mts +80 -0
- package/dist/selectors/balance.d.mts.map +1 -1
- package/dist/selectors/balance.mjs +186 -7
- package/dist/selectors/balance.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +20 -4
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +20 -4
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/dedupingBatchFetcher.cjs +168 -0
- package/dist/utils/dedupingBatchFetcher.cjs.map +1 -0
- package/dist/utils/dedupingBatchFetcher.d.cts +72 -0
- package/dist/utils/dedupingBatchFetcher.d.cts.map +1 -0
- package/dist/utils/dedupingBatchFetcher.d.mts +72 -0
- package/dist/utils/dedupingBatchFetcher.d.mts.map +1 -0
- package/dist/utils/dedupingBatchFetcher.mjs +164 -0
- package/dist/utils/dedupingBatchFetcher.mjs.map +1 -0
- 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 +7 -7
|
@@ -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_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_updateActive, _AssetsController_handleAccountTreeStateChange, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_getNativeAssetMap, _AssetsController_isNativeAsset, _AssetsController_getAssetType, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _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_refreshAssetsAfterNetworkChange;
|
|
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
|
|
@@ -186,8 +187,41 @@ function normalizeResponse(response) {
|
|
|
186
187
|
if (response.updateMode) {
|
|
187
188
|
normalized.updateMode = response.updateMode;
|
|
188
189
|
}
|
|
190
|
+
if (response.replaceCoveredChainBalances) {
|
|
191
|
+
normalized.replaceCoveredChainBalances = true;
|
|
192
|
+
}
|
|
189
193
|
return normalized;
|
|
190
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
|
+
}
|
|
191
225
|
// ============================================================================
|
|
192
226
|
// CONTROLLER IMPLEMENTATION
|
|
193
227
|
// ============================================================================
|
|
@@ -249,6 +283,8 @@ export class AssetsController extends BaseController {
|
|
|
249
283
|
/** Whether the keyring is unlocked. Combined with #uiOpen for #updateActive. */
|
|
250
284
|
_AssetsController_keyringUnlocked.set(this, false);
|
|
251
285
|
_AssetsController_controllerMutex.set(this, new Mutex());
|
|
286
|
+
/** Serializes account-switch fetch + subscribe to prevent overlapping races. */
|
|
287
|
+
_AssetsController_accountRefreshMutex.set(this, new Mutex());
|
|
252
288
|
/**
|
|
253
289
|
* Active balance subscriptions keyed by account ID.
|
|
254
290
|
* Each account has one logical subscription that may span multiple data sources.
|
|
@@ -412,9 +448,9 @@ export class AssetsController extends BaseController {
|
|
|
412
448
|
// creation, RPC is slow on many chains). Results are committed to state
|
|
413
449
|
// immediately so the UI can display balances without waiting for them.
|
|
414
450
|
//
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
//
|
|
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.
|
|
418
454
|
const fastSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
419
455
|
? [
|
|
420
456
|
createParallelBalanceMiddleware([
|
|
@@ -434,31 +470,36 @@ export class AssetsController extends BaseController {
|
|
|
434
470
|
]
|
|
435
471
|
: [__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f")];
|
|
436
472
|
const { response, durationByDataSource } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, fastSources, request);
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
473
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
474
|
+
...response,
|
|
475
|
+
updateMode: 'merge',
|
|
476
|
+
replaceCoveredChainBalances: true,
|
|
477
|
+
});
|
|
441
478
|
// Background pipeline: snap and RPC run in parallel after the fast path
|
|
442
479
|
// commits to state. Their balances are merged together before detection.
|
|
443
480
|
// Token + price enrichment matches the pre-split behavior: only when basic
|
|
444
481
|
// functionality is on (RPC-only mode must not call token/price APIs).
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
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
|
+
}
|
|
462
503
|
const durationMs = performance.now() - startTime;
|
|
463
504
|
// Emit trace for every full fetch (Assets Health dashboard)
|
|
464
505
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_FULL_FETCH, {
|
|
@@ -742,6 +783,8 @@ export class AssetsController extends BaseController {
|
|
|
742
783
|
if (!__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
|
|
743
784
|
return;
|
|
744
785
|
}
|
|
786
|
+
// Currency changed — old cached prices are in the wrong currency.
|
|
787
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").invalidatePriceCache();
|
|
745
788
|
this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this), {
|
|
746
789
|
forceUpdate: true,
|
|
747
790
|
dataTypes: ['price'],
|
|
@@ -848,7 +891,8 @@ export class AssetsController extends BaseController {
|
|
|
848
891
|
// RPC already fetches custom assets on purpose, and Snap handles non-EVM
|
|
849
892
|
// chains the rule does not apply to, so skip the middleware for those.
|
|
850
893
|
const shouldGraduateCustomAssets = sourceId === 'AccountsApiDataSource' ||
|
|
851
|
-
sourceId === 'BackendWebsocketDataSource'
|
|
894
|
+
sourceId === 'BackendWebsocketDataSource' ||
|
|
895
|
+
sourceId === 'AccountActivityService';
|
|
852
896
|
const enrichmentSources = [
|
|
853
897
|
...(shouldGraduateCustomAssets
|
|
854
898
|
? [__classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f")]
|
|
@@ -862,7 +906,10 @@ export class AssetsController extends BaseController {
|
|
|
862
906
|
]));
|
|
863
907
|
}
|
|
864
908
|
const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, enrichmentSources, pipelineRequest, response);
|
|
865
|
-
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this,
|
|
909
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
910
|
+
...enrichedResponse,
|
|
911
|
+
replaceCoveredChainBalances: response.replaceCoveredChainBalances,
|
|
912
|
+
});
|
|
866
913
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_UPDATE_PIPELINE, {
|
|
867
914
|
source: sourceId,
|
|
868
915
|
duration_ms: performance.now() - updateStart,
|
|
@@ -909,7 +956,7 @@ export class AssetsController extends BaseController {
|
|
|
909
956
|
this.messenger.unregisterActionHandler('AssetsController:setSelectedCurrency');
|
|
910
957
|
}
|
|
911
958
|
}
|
|
912
|
-
_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_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 = {
|
|
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 = {
|
|
913
960
|
controller: 'AssetsController',
|
|
914
961
|
}) {
|
|
915
962
|
if (!__classPrivateFieldGet(this, _AssetsController_trace, "f")) {
|
|
@@ -1035,11 +1082,11 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1035
1082
|
// The base-controller `:stateChange` event is guaranteed to fire
|
|
1036
1083
|
// when init() calls this.update(). #start() is idempotent so
|
|
1037
1084
|
// repeated fires are safe.
|
|
1038
|
-
this.messenger.subscribe('AccountTreeController:
|
|
1085
|
+
this.messenger.subscribe('AccountTreeController:stateChanged', () => {
|
|
1039
1086
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleAccountTreeStateChange).call(this);
|
|
1040
1087
|
});
|
|
1041
1088
|
// Subscribe to network enablement changes (only enabledNetworkMap)
|
|
1042
|
-
this.messenger.subscribe('NetworkEnablementController:
|
|
1089
|
+
this.messenger.subscribe('NetworkEnablementController:stateChanged', ({ enabledNetworkMap }) => {
|
|
1043
1090
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleEnabledNetworksChanged).call(this, enabledNetworkMap).catch(console.error);
|
|
1044
1091
|
});
|
|
1045
1092
|
// When a network is added or removed from NetworkController, refresh
|
|
@@ -1050,13 +1097,20 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1050
1097
|
// enabled in NetworkEnablementController.
|
|
1051
1098
|
this.messenger.subscribe('NetworkController:networkAdded', (networkConfiguration) => {
|
|
1052
1099
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleNetworkAdded).call(this, networkConfiguration.chainId);
|
|
1053
|
-
__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
|
+
});
|
|
1054
1103
|
});
|
|
1055
1104
|
this.messenger.subscribe('NetworkController:networkRemoved', () => {
|
|
1056
1105
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_refreshAssetsAfterNetworkChange).call(this);
|
|
1057
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
|
+
});
|
|
1058
1112
|
// Client + Keyring lifecycle: only run when UI is open AND keyring is unlocked
|
|
1059
|
-
this.messenger.subscribe('ClientController:
|
|
1113
|
+
this.messenger.subscribe('ClientController:stateChanged', (isUiOpen) => {
|
|
1060
1114
|
__classPrivateFieldSet(this, _AssetsController_uiOpen, isUiOpen, "f");
|
|
1061
1115
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateActive).call(this);
|
|
1062
1116
|
}, clientControllerSelectors.selectIsUiOpen);
|
|
@@ -1073,6 +1127,18 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1073
1127
|
this.messenger.subscribe('TransactionController:unapprovedTransactionAdded', (transactionMeta) => {
|
|
1074
1128
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_onUnapprovedTransactionAdded).call(this, transactionMeta);
|
|
1075
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
|
+
});
|
|
1076
1142
|
}, _AssetsController_onUnapprovedTransactionAdded = function _AssetsController_onUnapprovedTransactionAdded(transactionMeta) {
|
|
1077
1143
|
const hexChainId = transactionMeta.chainId;
|
|
1078
1144
|
if (!hexChainId) {
|
|
@@ -1095,6 +1161,46 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1095
1161
|
error,
|
|
1096
1162
|
});
|
|
1097
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
|
+
});
|
|
1098
1204
|
}, _AssetsController_updateActive = function _AssetsController_updateActive() {
|
|
1099
1205
|
const shouldRun = __classPrivateFieldGet(this, _AssetsController_uiOpen, "f") && __classPrivateFieldGet(this, _AssetsController_keyringUnlocked, "f");
|
|
1100
1206
|
if (shouldRun) {
|
|
@@ -1116,24 +1222,66 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1116
1222
|
if (!accountsChanged) {
|
|
1117
1223
|
return;
|
|
1118
1224
|
}
|
|
1225
|
+
const hasOverlap = [...currentIds].some((id) => __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").has(id));
|
|
1226
|
+
if (!hasOverlap && __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").size > 0) {
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1119
1229
|
log('Account tree changed with new accounts, re-subscribing', {
|
|
1120
1230
|
previousCount: __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").size,
|
|
1121
1231
|
currentCount: currentIds.size,
|
|
1122
1232
|
});
|
|
1123
1233
|
__classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, currentIds, "f");
|
|
1124
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1125
1234
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
1126
1235
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1127
|
-
this.
|
|
1128
|
-
|
|
1129
|
-
forceUpdate: true,
|
|
1130
|
-
}).catch((error) => {
|
|
1131
|
-
log('Failed to fetch assets after tree change', error);
|
|
1236
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_runAccountTreeRefresh).call(this, accounts).catch((error) => {
|
|
1237
|
+
log('Failed to refresh assets after tree change', error);
|
|
1132
1238
|
});
|
|
1133
1239
|
}
|
|
1134
1240
|
else {
|
|
1135
1241
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_start).call(this);
|
|
1136
1242
|
}
|
|
1243
|
+
}, _AssetsController_runAccountTreeRefresh = async function _AssetsController_runAccountTreeRefresh(accounts) {
|
|
1244
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_accountRefreshMutex, "f").acquire();
|
|
1245
|
+
try {
|
|
1246
|
+
await this.getAssets(accounts, {
|
|
1247
|
+
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
1248
|
+
forceUpdate: true,
|
|
1249
|
+
});
|
|
1250
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1251
|
+
}
|
|
1252
|
+
catch (error) {
|
|
1253
|
+
log('Failed to fetch assets after tree change', error);
|
|
1254
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1255
|
+
}
|
|
1256
|
+
finally {
|
|
1257
|
+
releaseLock();
|
|
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
|
+
}
|
|
1137
1285
|
}, _AssetsController_registerActionHandlers = function _AssetsController_registerActionHandlers() {
|
|
1138
1286
|
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
1139
1287
|
}, _AssetsController_handleActiveChainsUpdate = function _AssetsController_handleActiveChainsUpdate(dataSourceId, activeChains, previousChains) {
|
|
@@ -1150,23 +1298,12 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1150
1298
|
const addedChains = activeChains.filter((ch) => !previousSet.has(ch));
|
|
1151
1299
|
const removedChains = previous.filter((ch) => !activeChains.includes(ch));
|
|
1152
1300
|
if (addedChains.length > 0 || removedChains.length > 0) {
|
|
1153
|
-
// Refresh subscriptions to use updated data source availability
|
|
1301
|
+
// Refresh subscriptions to use updated data source availability.
|
|
1302
|
+
// No one-time fetch needed here — #handleEnabledNetworksChanged
|
|
1303
|
+
// handles fetches when the user enables a network, and
|
|
1304
|
+
// #subscribeAssets re-subscribes with the correct chain assignment.
|
|
1154
1305
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1155
1306
|
}
|
|
1156
|
-
// If chains were added and we have selected accounts, do one-time fetch
|
|
1157
|
-
if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).length > 0) {
|
|
1158
|
-
const addedEnabledChains = addedChains.filter((chain) => __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").has(chain));
|
|
1159
|
-
if (addedEnabledChains.length > 0) {
|
|
1160
|
-
log('Fetching balances for newly added chains', { addedEnabledChains });
|
|
1161
|
-
this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this), {
|
|
1162
|
-
chainIds: addedEnabledChains,
|
|
1163
|
-
forceUpdate: true,
|
|
1164
|
-
updateMode: 'merge',
|
|
1165
|
-
}).catch((error) => {
|
|
1166
|
-
log('Failed to fetch balance for added chains', { error });
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
1307
|
}, _AssetsController_executeMiddlewares =
|
|
1171
1308
|
// ============================================================================
|
|
1172
1309
|
// MIDDLEWARE EXECUTION
|
|
@@ -1258,6 +1395,41 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1258
1395
|
});
|
|
1259
1396
|
}
|
|
1260
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
|
+
});
|
|
1261
1433
|
}, _AssetsController_getNativeAssetMap = function _AssetsController_getNativeAssetMap() {
|
|
1262
1434
|
return (__classPrivateFieldGet(this, _AssetsController_queryApiClient, "f").getCachedData(NATIVE_ASSETS_QUERY_KEY) ?? {});
|
|
1263
1435
|
}, _AssetsController_isNativeAsset = function _AssetsController_isNativeAsset(assetId) {
|
|
@@ -1299,6 +1471,17 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1299
1471
|
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_resolveNativeAssetIds).call(this, __classPrivateFieldGet(this, _AssetsController_enabledChains, "f"));
|
|
1300
1472
|
}, _AssetsController_getNativeAssetIdsForAccount = function _AssetsController_getNativeAssetIdsForAccount(account) {
|
|
1301
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
|
+
});
|
|
1302
1485
|
}, _AssetsController_ensureNativeBalancesDefaultZero = function _AssetsController_ensureNativeBalancesDefaultZero() {
|
|
1303
1486
|
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
1304
1487
|
if (accounts.length === 0) {
|
|
@@ -1316,7 +1499,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1316
1499
|
balances[accountId] = {};
|
|
1317
1500
|
}
|
|
1318
1501
|
for (const nativeAssetId of nativeAssetIds) {
|
|
1319
|
-
if (!(
|
|
1502
|
+
if (!Object.prototype.hasOwnProperty.call(balances[accountId], nativeAssetId)) {
|
|
1320
1503
|
balances[accountId][nativeAssetId] = { amount: '0' };
|
|
1321
1504
|
}
|
|
1322
1505
|
}
|
|
@@ -1433,43 +1616,16 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1433
1616
|
for (const [accountId, accountBalances] of Object.entries(normalizedResponse.assetsBalance)) {
|
|
1434
1617
|
const previousBalances = previousState.assetsBalance[accountId] ?? {};
|
|
1435
1618
|
const customAssetIds = state.customAssets[accountId] ?? [];
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
// are never inadvertently reset to zero.
|
|
1440
|
-
// Merge: response overlays previous balances.
|
|
1441
|
-
const effective = mode === 'merge'
|
|
1442
|
-
? { ...previousBalances, ...accountBalances }
|
|
1443
|
-
: (() => {
|
|
1444
|
-
// Determine which chain namespaces this response covers.
|
|
1445
|
-
const coveredChains = new Set(Object.keys(accountBalances).map((assetId) => assetId.split('/')[0]));
|
|
1446
|
-
// Start from previous balances, dropping only entries for
|
|
1447
|
-
// chains this response is authoritative over.
|
|
1448
|
-
const next = {};
|
|
1449
|
-
for (const [assetId, balance] of Object.entries(previousBalances)) {
|
|
1450
|
-
if (!coveredChains.has(assetId.split('/')[0])) {
|
|
1451
|
-
next[assetId] = balance;
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
// Apply the response (authoritative for covered chains).
|
|
1455
|
-
Object.assign(next, accountBalances);
|
|
1456
|
-
// Preserve custom assets that the response omitted.
|
|
1457
|
-
for (const customId of customAssetIds) {
|
|
1458
|
-
if (!(customId in next)) {
|
|
1459
|
-
const prev = previousBalances[customId];
|
|
1460
|
-
next[customId] =
|
|
1461
|
-
prev ?? { amount: '0' };
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
return next;
|
|
1465
|
-
})();
|
|
1619
|
+
const replaceCoveredChains = mode === 'full' ||
|
|
1620
|
+
normalizedResponse.replaceCoveredChainBalances === true;
|
|
1621
|
+
const effective = mergeAccountBalances(previousBalances, accountBalances, customAssetIds, replaceCoveredChains);
|
|
1466
1622
|
// Ensure native tokens have an entry (0 if missing) for chains this account supports
|
|
1467
1623
|
const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.id === accountId);
|
|
1468
1624
|
const nativeAssetIdsForAccount = account
|
|
1469
1625
|
? __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForAccount).call(this, account)
|
|
1470
1626
|
: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForEnabledChains).call(this);
|
|
1471
1627
|
for (const nativeAssetId of nativeAssetIdsForAccount) {
|
|
1472
|
-
if (!(nativeAssetId
|
|
1628
|
+
if (!Object.prototype.hasOwnProperty.call(effective, nativeAssetId)) {
|
|
1473
1629
|
effective[nativeAssetId] = { amount: '0' };
|
|
1474
1630
|
}
|
|
1475
1631
|
}
|
|
@@ -1501,7 +1657,6 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1501
1657
|
balances[accountId] = effective;
|
|
1502
1658
|
}
|
|
1503
1659
|
}
|
|
1504
|
-
// Update prices in state
|
|
1505
1660
|
if (normalizedResponse.assetsPrice) {
|
|
1506
1661
|
for (const [key, value] of Object.entries(normalizedResponse.assetsPrice)) {
|
|
1507
1662
|
prices[key] = value;
|
|
@@ -1662,14 +1817,8 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1662
1817
|
enabledChainCount: chainIds.length,
|
|
1663
1818
|
});
|
|
1664
1819
|
__classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(accounts.map((a) => a.id)), "f");
|
|
1665
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m",
|
|
1666
|
-
|
|
1667
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1668
|
-
this.getAssets(accounts, {
|
|
1669
|
-
chainIds,
|
|
1670
|
-
forceUpdate: true,
|
|
1671
|
-
}).catch((error) => {
|
|
1672
|
-
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);
|
|
1673
1822
|
});
|
|
1674
1823
|
}, _AssetsController_stop = function _AssetsController_stop() {
|
|
1675
1824
|
log('Stopping asset tracking', {
|
|
@@ -1747,7 +1896,13 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1747
1896
|
const seenIds = new Set();
|
|
1748
1897
|
const accountsForSource = assignedChains
|
|
1749
1898
|
.flatMap((chainId) => chainToAccounts.get(chainId) ?? [])
|
|
1750
|
-
.filter((account) =>
|
|
1899
|
+
.filter((account) => {
|
|
1900
|
+
if (seenIds.has(account.id)) {
|
|
1901
|
+
return false;
|
|
1902
|
+
}
|
|
1903
|
+
seenIds.add(account.id);
|
|
1904
|
+
return true;
|
|
1905
|
+
});
|
|
1751
1906
|
if (accountsForSource.length > 0) {
|
|
1752
1907
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accountsForSource, assignedChains);
|
|
1753
1908
|
}
|
|
@@ -1934,16 +2089,22 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
1934
2089
|
accountIds: accounts.map((a) => a.id),
|
|
1935
2090
|
});
|
|
1936
2091
|
__classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(accounts.map((a) => a.id)), "f");
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
2092
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_accountRefreshMutex, "f").acquire();
|
|
2093
|
+
try {
|
|
2094
|
+
if (accounts.length > 0) {
|
|
2095
|
+
await this.getAssets(accounts, {
|
|
2096
|
+
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
2097
|
+
forceUpdate: true,
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
// Subscribe after fetch so WS notifications can recover state
|
|
2101
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
2102
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
2103
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
2104
|
+
}
|
|
2105
|
+
finally {
|
|
2106
|
+
releaseLock();
|
|
1944
2107
|
}
|
|
1945
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
1946
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1947
2108
|
}, _AssetsController_handleEnabledNetworksChanged = async function _AssetsController_handleEnabledNetworksChanged(enabledNetworkMap) {
|
|
1948
2109
|
const previousChains = __classPrivateFieldGet(this, _AssetsController_enabledChains, "f");
|
|
1949
2110
|
__classPrivateFieldSet(this, _AssetsController_enabledChains, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_extractEnabledChains).call(this, enabledNetworkMap), "f");
|
|
@@ -2003,11 +2164,102 @@ async function _AssetsController_handleAccountGroupChanged() {
|
|
|
2003
2164
|
caipChainId,
|
|
2004
2165
|
});
|
|
2005
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
|
+
}
|
|
2006
2228
|
}, _AssetsController_refreshAssetsAfterNetworkChange = function _AssetsController_refreshAssetsAfterNetworkChange() {
|
|
2007
|
-
|
|
2229
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2230
|
+
if (accounts.length === 0) {
|
|
2231
|
+
return;
|
|
2232
|
+
}
|
|
2233
|
+
this.getAssets(accounts, {
|
|
2008
2234
|
forceUpdate: true,
|
|
2235
|
+
dataTypes: ['balance', 'metadata'],
|
|
2009
2236
|
}).catch((error) => {
|
|
2010
2237
|
log('Failed to refresh assets after network change', { error });
|
|
2011
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]);
|
|
2012
2264
|
};
|
|
2013
2265
|
//# sourceMappingURL=AssetsController.mjs.map
|