@metamask-previews/assets-controller 9.1.0-preview-ba933fc1b → 9.1.0-preview-a4e0c04
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 +2 -5
- package/dist/AssetsController.cjs +106 -65
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts +1 -1
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts +1 -1
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +106 -65
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.cjs +1 -1
- package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.mjs +1 -1
- package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.cjs +16 -21
- package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.mjs +16 -21
- package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
- package/dist/data-sources/RpcDataSource.cjs +2 -3
- package/dist/data-sources/RpcDataSource.cjs.map +1 -1
- package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
- package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
- package/dist/data-sources/RpcDataSource.mjs +2 -3
- package/dist/data-sources/RpcDataSource.mjs.map +1 -1
- package/dist/data-sources/SnapDataSource.cjs +3 -3
- package/dist/data-sources/SnapDataSource.cjs.map +1 -1
- package/dist/data-sources/SnapDataSource.mjs +3 -3
- package/dist/data-sources/SnapDataSource.mjs.map +1 -1
- package/dist/middlewares/ParallelMiddleware.cjs +0 -9
- 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 +0 -9
- package/dist/middlewares/ParallelMiddleware.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +10 -8
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +10 -8
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -13,12 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
13
13
|
|
|
14
14
|
### Fixed
|
|
15
15
|
|
|
16
|
-
- Fix stale token balances after transactions when switching accounts or when websocket subscriptions reconnect; `AssetsController` now fetches before re-subscribing on account switch
|
|
16
|
+
- Fix stale token balances after transactions when switching accounts or when websocket subscriptions reconnect; `AssetsController` now fetches before re-subscribing on account switch, serializes overlapping refresh work, treats `getAssets({ forceUpdate: true })` as authoritative over recent websocket freshness guards, and prevents passive polling from overwriting websocket balances for 120 seconds ([#9265](https://github.com/MetaMask/core/pull/9265))
|
|
17
17
|
- `AccountsApiDataSource` bypasses the TanStack Query balance cache when `forceUpdate` is true so forced refreshes return up-to-date balances instead of 60-second cached values ([#9265](https://github.com/MetaMask/core/pull/9265))
|
|
18
|
-
- `BackendWebsocketDataSource` re-subscribes when subscribed accounts change (case-insensitive EVM address matching), serializes subscribe/unsubscribe to prevent races on account switch, and registers channel callbacks
|
|
19
|
-
- Remove the 120-second websocket balance freshness guard that blocked force-refresh and polling updates from correcting stale websocket balances ([#9273](https://github.com/MetaMask/core/pull/9273))
|
|
20
|
-
- Add `update` balance update mode so fetch and force-refresh pipelines patch balances without removing tokens omitted from partial API snapshots; `getAssets({ forceUpdate: true })`, `AccountsApiDataSource`, and `SnapDataSource` use this mode ([#9273](https://github.com/MetaMask/core/pull/9273))
|
|
21
|
-
- `BackendWebsocketDataSource` registers subscription handlers before the subscribe handshake so in-flight account-activity notifications are not dropped, cleans up subscription state on subscribe failure, and resolves balance updates from stored subscription state when notifications arrive with stale subscription IDs ([#9273](https://github.com/MetaMask/core/pull/9273))
|
|
18
|
+
- `BackendWebsocketDataSource` re-subscribes when subscribed accounts change (case-insensitive EVM address matching), serializes subscribe/unsubscribe to prevent races on account switch, and registers optional channel callbacks for more reliable notification delivery ([#9265](https://github.com/MetaMask/core/pull/9265))
|
|
22
19
|
|
|
23
20
|
## [9.1.0]
|
|
24
21
|
|
|
@@ -13,7 +13,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_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_updateActive, _AssetsController_handleAccountTreeStateChange, _AssetsController_runAccountTreeRefresh, _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;
|
|
16
|
+
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_wsBalanceFreshUntil, _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_runAccountTreeRefresh, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_getNativeAssetMap, _AssetsController_isNativeAsset, _AssetsController_getAssetType, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_ensureDefaultTrackedAssetsSeeded, _AssetsController_filterBalancesRespectingWsFreshness, _AssetsController_markWsBalancesFresh, _AssetsController_clearWsBalanceFreshness, _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;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.AssetsController = exports.getDefaultAssetsControllerState = void 0;
|
|
19
19
|
const base_controller_1 = require("@metamask/base-controller");
|
|
@@ -62,6 +62,15 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
62
62
|
];
|
|
63
63
|
/** Default polling interval hint for data sources (30 seconds) */
|
|
64
64
|
const DEFAULT_POLLING_INTERVAL_MS = 30000;
|
|
65
|
+
/** Sources whose passive polling must not overwrite recent websocket balances. */
|
|
66
|
+
const POLLING_BALANCE_SOURCES = new Set([
|
|
67
|
+
'AccountsApiDataSource',
|
|
68
|
+
'RpcDataSource',
|
|
69
|
+
'SnapDataSource',
|
|
70
|
+
'StakedBalanceDataSource',
|
|
71
|
+
]);
|
|
72
|
+
/** How long websocket balance updates block stale polling overwrites. */
|
|
73
|
+
const WS_BALANCE_FRESHNESS_MS = 120000;
|
|
65
74
|
// ============================================================================
|
|
66
75
|
// TRACE NAMES — used in Sentry spans (search these strings in Discover)
|
|
67
76
|
// ============================================================================
|
|
@@ -192,6 +201,9 @@ function normalizeResponse(response) {
|
|
|
192
201
|
if (response.updateMode) {
|
|
193
202
|
normalized.updateMode = response.updateMode;
|
|
194
203
|
}
|
|
204
|
+
if (response.sourceId) {
|
|
205
|
+
normalized.sourceId = response.sourceId;
|
|
206
|
+
}
|
|
195
207
|
return normalized;
|
|
196
208
|
}
|
|
197
209
|
// ============================================================================
|
|
@@ -272,6 +284,11 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
272
284
|
* re-subscriptions when the account set hasn't actually changed.
|
|
273
285
|
*/
|
|
274
286
|
_AssetsController_lastKnownAccountIds.set(this, new Set());
|
|
287
|
+
/**
|
|
288
|
+
* Per `accountId:assetId`, timestamp until which websocket balance updates
|
|
289
|
+
* should not be overwritten by polling/API fetches.
|
|
290
|
+
*/
|
|
291
|
+
_AssetsController_wsBalanceFreshUntil.set(this, new Map());
|
|
275
292
|
_AssetsController_backendWebsocketDataSource.set(this, void 0);
|
|
276
293
|
_AssetsController_accountsApiDataSource.set(this, void 0);
|
|
277
294
|
_AssetsController_snapDataSource.set(this, void 0);
|
|
@@ -420,9 +437,9 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
420
437
|
// creation, RPC is slow on many chains). Results are committed to state
|
|
421
438
|
// immediately so the UI can display balances without waiting for them.
|
|
422
439
|
//
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
//
|
|
440
|
+
// Both the fast and background pipelines use 'merge' mode because neither
|
|
441
|
+
// alone represents the full set of data sources. Using 'full' in either
|
|
442
|
+
// would wipe balances from the sources handled by the other pipeline.
|
|
426
443
|
const fastSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
427
444
|
? [
|
|
428
445
|
(0, ParallelMiddleware_1.createParallelBalanceMiddleware)([
|
|
@@ -442,7 +459,14 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
442
459
|
]
|
|
443
460
|
: [__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f")];
|
|
444
461
|
const { response, durationByDataSource } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, fastSources, request);
|
|
445
|
-
|
|
462
|
+
// The fast pipeline only contains a subset of data sources (AccountsApi +
|
|
463
|
+
// StakedBalance), so it must always merge to avoid wiping Snap/RPC
|
|
464
|
+
// balances that the background pipeline hasn't yet replaced.
|
|
465
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
466
|
+
...response,
|
|
467
|
+
updateMode: 'merge',
|
|
468
|
+
sourceId: 'getAssets:forceUpdate',
|
|
469
|
+
});
|
|
446
470
|
// Background pipeline: snap and RPC run in parallel after the fast path
|
|
447
471
|
// commits to state. Their balances are merged together before detection.
|
|
448
472
|
// Token + price enrichment matches the pre-split behavior: only when basic
|
|
@@ -462,7 +486,11 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
462
486
|
]
|
|
463
487
|
: []),
|
|
464
488
|
], request)
|
|
465
|
-
.then(({ response: slowResponse }) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
489
|
+
.then(({ response: slowResponse }) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
490
|
+
...slowResponse,
|
|
491
|
+
updateMode: 'merge',
|
|
492
|
+
sourceId: 'getAssets:forceUpdate',
|
|
493
|
+
}))
|
|
466
494
|
.catch((error) => log('Background pipeline failed', { error }));
|
|
467
495
|
const durationMs = performance.now() - startTime;
|
|
468
496
|
// Emit trace for every full fetch (Assets Health dashboard)
|
|
@@ -869,7 +897,11 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
869
897
|
]));
|
|
870
898
|
}
|
|
871
899
|
const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, enrichmentSources, pipelineRequest, response);
|
|
872
|
-
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, enrichedResponse);
|
|
900
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, { ...enrichedResponse, sourceId });
|
|
901
|
+
if (sourceId === 'BackendWebsocketDataSource' &&
|
|
902
|
+
enrichedResponse.assetsBalance) {
|
|
903
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_markWsBalancesFresh).call(this, enrichedResponse.assetsBalance);
|
|
904
|
+
}
|
|
873
905
|
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_UPDATE_PIPELINE, {
|
|
874
906
|
source: sourceId,
|
|
875
907
|
duration_ms: performance.now() - updateStart,
|
|
@@ -917,7 +949,7 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
917
949
|
}
|
|
918
950
|
}
|
|
919
951
|
exports.AssetsController = AssetsController;
|
|
920
|
-
_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 = {
|
|
952
|
+
_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_wsBalanceFreshUntil = 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 = {
|
|
921
953
|
controller: 'AssetsController',
|
|
922
954
|
}) {
|
|
923
955
|
if (!__classPrivateFieldGet(this, _AssetsController_trace, "f")) {
|
|
@@ -1379,9 +1411,37 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1379
1411
|
}
|
|
1380
1412
|
}
|
|
1381
1413
|
});
|
|
1414
|
+
}, _AssetsController_filterBalancesRespectingWsFreshness = function _AssetsController_filterBalancesRespectingWsFreshness(accountId, accountBalances, sourceId) {
|
|
1415
|
+
if (!sourceId || !POLLING_BALANCE_SOURCES.has(sourceId)) {
|
|
1416
|
+
return accountBalances;
|
|
1417
|
+
}
|
|
1418
|
+
const now = Date.now();
|
|
1419
|
+
const filtered = {};
|
|
1420
|
+
for (const [assetId, balance] of Object.entries(accountBalances)) {
|
|
1421
|
+
const freshUntil = __classPrivateFieldGet(this, _AssetsController_wsBalanceFreshUntil, "f").get(`${accountId}:${assetId}`);
|
|
1422
|
+
if (freshUntil !== undefined && now < freshUntil) {
|
|
1423
|
+
continue;
|
|
1424
|
+
}
|
|
1425
|
+
filtered[assetId] = balance;
|
|
1426
|
+
}
|
|
1427
|
+
return filtered;
|
|
1428
|
+
}, _AssetsController_markWsBalancesFresh = function _AssetsController_markWsBalancesFresh(assetsBalance) {
|
|
1429
|
+
const freshUntil = Date.now() + WS_BALANCE_FRESHNESS_MS;
|
|
1430
|
+
for (const [accountId, balances] of Object.entries(assetsBalance)) {
|
|
1431
|
+
for (const assetId of Object.keys(balances)) {
|
|
1432
|
+
__classPrivateFieldGet(this, _AssetsController_wsBalanceFreshUntil, "f").set(`${accountId}:${assetId}`, freshUntil);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
}, _AssetsController_clearWsBalanceFreshness = function _AssetsController_clearWsBalanceFreshness(assetsBalance) {
|
|
1436
|
+
for (const [accountId, balances] of Object.entries(assetsBalance)) {
|
|
1437
|
+
for (const assetId of Object.keys(balances)) {
|
|
1438
|
+
__classPrivateFieldGet(this, _AssetsController_wsBalanceFreshUntil, "f").delete(`${accountId}:${assetId}`);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1382
1441
|
}, _AssetsController_updateState = async function _AssetsController_updateState(response) {
|
|
1383
1442
|
const normalizedResponse = normalizeResponse(response);
|
|
1384
1443
|
const mode = normalizedResponse.updateMode ?? 'merge';
|
|
1444
|
+
const assetsBalanceToApply = normalizedResponse.assetsBalance;
|
|
1385
1445
|
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_controllerMutex, "f").acquire();
|
|
1386
1446
|
try {
|
|
1387
1447
|
const previousState = this.state;
|
|
@@ -1397,43 +1457,29 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1397
1457
|
const balances = state.assetsBalance;
|
|
1398
1458
|
const prices = state.assetsPrice;
|
|
1399
1459
|
if (normalizedResponse.assetsInfo) {
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
// but seed entries that are missing so RPC-only chains (e.g.
|
|
1403
|
-
// Avalanche) can render native balances on first fetch.
|
|
1404
|
-
for (const [key, value] of Object.entries(normalizedResponse.assetsInfo)) {
|
|
1405
|
-
if (metadata[key]) {
|
|
1406
|
-
continue;
|
|
1407
|
-
}
|
|
1408
|
-
metadata[key] = value;
|
|
1460
|
+
for (const [key, value] of Object.entries(normalizedResponse.assetsInfo)) {
|
|
1461
|
+
if (!(0, lodash_1.isEqual)(previousState.assetsInfo[key], value)) {
|
|
1409
1462
|
changedMetadata.push(key);
|
|
1410
1463
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
for
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
decimals: existing.decimals ?? incoming.decimals,
|
|
1431
|
-
image: existing.image ?? incoming.image,
|
|
1432
|
-
};
|
|
1433
|
-
}
|
|
1434
|
-
else {
|
|
1435
|
-
metadata[key] = value;
|
|
1436
|
-
}
|
|
1464
|
+
const existing = metadata[key];
|
|
1465
|
+
const incoming = value;
|
|
1466
|
+
// When the API returns no symbol or name for this token, it has no
|
|
1467
|
+
// real knowledge of it (e.g. a user-deployed token not indexed by
|
|
1468
|
+
// the API). Preserve richer metadata already in state (e.g. from
|
|
1469
|
+
// pendingMetadata set by addCustomAsset) so that the correct
|
|
1470
|
+
// decimals/symbol/name/image are not overwritten with empty values.
|
|
1471
|
+
if (existing && !incoming.symbol && !incoming.name) {
|
|
1472
|
+
metadata[key] = {
|
|
1473
|
+
...existing,
|
|
1474
|
+
...incoming,
|
|
1475
|
+
symbol: existing.symbol,
|
|
1476
|
+
name: existing.name,
|
|
1477
|
+
decimals: existing.decimals ?? incoming.decimals,
|
|
1478
|
+
image: existing.image ?? incoming.image,
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
else {
|
|
1482
|
+
metadata[key] = value;
|
|
1437
1483
|
}
|
|
1438
1484
|
}
|
|
1439
1485
|
}
|
|
@@ -1456,21 +1502,21 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1456
1502
|
}
|
|
1457
1503
|
}
|
|
1458
1504
|
}
|
|
1459
|
-
if (
|
|
1460
|
-
for (const [accountId, accountBalances] of Object.entries(
|
|
1505
|
+
if (assetsBalanceToApply) {
|
|
1506
|
+
for (const [accountId, accountBalances] of Object.entries(assetsBalanceToApply)) {
|
|
1507
|
+
const filteredAccountBalances = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_filterBalancesRespectingWsFreshness).call(this, accountId, accountBalances, normalizedResponse.sourceId);
|
|
1461
1508
|
const previousBalances = previousState.assetsBalance[accountId] ?? {};
|
|
1462
1509
|
const customAssetIds = state.customAssets[accountId] ?? [];
|
|
1463
1510
|
// Full: response is authoritative for the chains it covered;
|
|
1464
1511
|
// balances for chains not in the response are preserved from
|
|
1465
1512
|
// previous state so unsupported chains (e.g. Ink on AccountsAPI)
|
|
1466
1513
|
// are never inadvertently reset to zero.
|
|
1467
|
-
// Merge
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
? { ...previousBalances, ...accountBalances }
|
|
1514
|
+
// Merge: response overlays previous balances.
|
|
1515
|
+
const effective = mode === 'merge'
|
|
1516
|
+
? { ...previousBalances, ...filteredAccountBalances }
|
|
1471
1517
|
: (() => {
|
|
1472
1518
|
// Determine which chain namespaces this response covers.
|
|
1473
|
-
const coveredChains = new Set(Object.keys(
|
|
1519
|
+
const coveredChains = new Set(Object.keys(filteredAccountBalances).map((assetId) => assetId.split('/')[0]));
|
|
1474
1520
|
// Start from previous balances, dropping only entries for
|
|
1475
1521
|
// chains this response is authoritative over.
|
|
1476
1522
|
const next = {};
|
|
@@ -1480,7 +1526,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1480
1526
|
}
|
|
1481
1527
|
}
|
|
1482
1528
|
// Apply the response (authoritative for covered chains).
|
|
1483
|
-
Object.assign(next,
|
|
1529
|
+
Object.assign(next, filteredAccountBalances);
|
|
1484
1530
|
// Preserve custom assets that the response omitted.
|
|
1485
1531
|
for (const customId of customAssetIds) {
|
|
1486
1532
|
if (!(customId in next)) {
|
|
@@ -1529,21 +1575,10 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1529
1575
|
balances[accountId] = effective;
|
|
1530
1576
|
}
|
|
1531
1577
|
}
|
|
1532
|
-
// Update prices in state
|
|
1533
|
-
// balance-only refreshes do not clobber existing price data.
|
|
1578
|
+
// Update prices in state
|
|
1534
1579
|
if (normalizedResponse.assetsPrice) {
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
if (prices[key]) {
|
|
1538
|
-
continue;
|
|
1539
|
-
}
|
|
1540
|
-
prices[key] = value;
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
else {
|
|
1544
|
-
for (const [key, value] of Object.entries(normalizedResponse.assetsPrice)) {
|
|
1545
|
-
prices[key] = value;
|
|
1546
|
-
}
|
|
1580
|
+
for (const [key, value] of Object.entries(normalizedResponse.assetsPrice)) {
|
|
1581
|
+
prices[key] = value;
|
|
1547
1582
|
}
|
|
1548
1583
|
}
|
|
1549
1584
|
});
|
|
@@ -1603,6 +1638,12 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1603
1638
|
});
|
|
1604
1639
|
}
|
|
1605
1640
|
}
|
|
1641
|
+
// Authoritative fetch on account switch — drop WS freshness locks so API
|
|
1642
|
+
// balances (e.g. receiver +1 USDC) replace stale values from a prior send.
|
|
1643
|
+
if (normalizedResponse.sourceId === 'getAssets:forceUpdate' &&
|
|
1644
|
+
assetsBalanceToApply) {
|
|
1645
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_clearWsBalanceFreshness).call(this, assetsBalanceToApply);
|
|
1646
|
+
}
|
|
1606
1647
|
}
|
|
1607
1648
|
finally {
|
|
1608
1649
|
releaseLock();
|