@metamask-previews/assets-controllers 106.0.0-preview-beaf51362 → 106.0.0-preview-55fbbe681

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +0 -8
  2. package/dist/MultichainAssetsController/MultichainAssetsController.cjs +157 -144
  3. package/dist/MultichainAssetsController/MultichainAssetsController.cjs.map +1 -1
  4. package/dist/MultichainAssetsController/MultichainAssetsController.d.cts +6 -17
  5. package/dist/MultichainAssetsController/MultichainAssetsController.d.cts.map +1 -1
  6. package/dist/MultichainAssetsController/MultichainAssetsController.d.mts +6 -17
  7. package/dist/MultichainAssetsController/MultichainAssetsController.d.mts.map +1 -1
  8. package/dist/MultichainAssetsController/MultichainAssetsController.mjs +157 -144
  9. package/dist/MultichainAssetsController/MultichainAssetsController.mjs.map +1 -1
  10. package/dist/MultichainBalancesController/MultichainBalancesController.cjs +77 -44
  11. package/dist/MultichainBalancesController/MultichainBalancesController.cjs.map +1 -1
  12. package/dist/MultichainBalancesController/MultichainBalancesController.d.cts +18 -5
  13. package/dist/MultichainBalancesController/MultichainBalancesController.d.cts.map +1 -1
  14. package/dist/MultichainBalancesController/MultichainBalancesController.d.mts +18 -5
  15. package/dist/MultichainBalancesController/MultichainBalancesController.d.mts.map +1 -1
  16. package/dist/MultichainBalancesController/MultichainBalancesController.mjs +77 -44
  17. package/dist/MultichainBalancesController/MultichainBalancesController.mjs.map +1 -1
  18. package/dist/MultichainBalancesController/index.cjs.map +1 -1
  19. package/dist/MultichainBalancesController/index.d.cts +1 -1
  20. package/dist/MultichainBalancesController/index.d.cts.map +1 -1
  21. package/dist/MultichainBalancesController/index.d.mts +1 -1
  22. package/dist/MultichainBalancesController/index.d.mts.map +1 -1
  23. package/dist/MultichainBalancesController/index.mjs.map +1 -1
  24. package/dist/multichain/stellarAccountAssetInfo.cjs +87 -0
  25. package/dist/multichain/stellarAccountAssetInfo.cjs.map +1 -0
  26. package/dist/multichain/stellarAccountAssetInfo.d.cts +47 -0
  27. package/dist/multichain/stellarAccountAssetInfo.d.cts.map +1 -0
  28. package/dist/multichain/stellarAccountAssetInfo.d.mts +47 -0
  29. package/dist/multichain/stellarAccountAssetInfo.d.mts.map +1 -0
  30. package/dist/multichain/stellarAccountAssetInfo.mjs +77 -0
  31. package/dist/multichain/stellarAccountAssetInfo.mjs.map +1 -0
  32. package/dist/selectors/token-selectors.cjs +15 -13
  33. package/dist/selectors/token-selectors.cjs.map +1 -1
  34. package/dist/selectors/token-selectors.d.cts +19 -50
  35. package/dist/selectors/token-selectors.d.cts.map +1 -1
  36. package/dist/selectors/token-selectors.d.mts +19 -50
  37. package/dist/selectors/token-selectors.d.mts.map +1 -1
  38. package/dist/selectors/token-selectors.mjs +15 -13
  39. package/dist/selectors/token-selectors.mjs.map +1 -1
  40. package/package.json +6 -6
package/CHANGELOG.md CHANGED
@@ -18,14 +18,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
18
18
  - `MultichainAssetsController`: after `addAssets`, re-fetch the Snap `listAccountAssets` list for Stellar classic (`asset:`) ids and clear `stellarClassicTrustlineInactiveAssetIds` when the keyring already reports the same CAIP-19 id (e.g. hide token then re-add while trustline is still active) ([#TODO](https://github.com/MetaMask/core/pull/TODO))
19
19
  - `MultichainBalancesController`: when `MultichainAssetsController:accountAssetListUpdated` fires while the vault is locked, balance fetches are skipped and were never retried after unlock, leaving multichain token lists empty despite assets in state; subscribe to `KeyringController:stateChange` and refetch balances for snap-backed accounts that still have no cached balances after unlock. ([#TODO](https://github.com/MetaMask/core/pull/TODO))
20
20
 
21
- ### Changed
22
-
23
- - Bump `@metamask/account-tree-controller` from `^7.2.0` to `^7.3.0` ([#8722](https://github.com/MetaMask/core/pull/8722))
24
- - Bump `@metamask/keyring-controller` from `^25.4.0` to `^25.5.0` ([#8722](https://github.com/MetaMask/core/pull/8722))
25
- - Bump `@metamask/multichain-account-service` from `^8.0.1` to `^9.0.0` ([#8722](https://github.com/MetaMask/core/pull/8722))
26
- - Bump `@metamask/permission-controller` from `^13.0.0` to `^13.1.0` ([#8722](https://github.com/MetaMask/core/pull/8722))
27
- - Bump `@metamask/transaction-controller` from `^65.1.0` to `^65.2.0` ([#8722](https://github.com/MetaMask/core/pull/8722))
28
-
29
21
  ## [106.0.0]
30
22
 
31
23
  ### Added
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _MultichainAssetsController_instances, _MultichainAssetsController_snaps, _MultichainAssetsController_controllerOperationMutex, _MultichainAssetsController_backfillStellarTrustlineInactiveIfNeeded, _MultichainAssetsController_handleAccountAssetListUpdatedEvent, _MultichainAssetsController_handleOnAccountAddedEvent, _MultichainAssetsController_isAssetIgnored, _MultichainAssetsController_reconcileStellarClassicTrustlineInactiveWithSnap, _MultichainAssetsController_removeStellarTrustlineInactiveAssetIds, _MultichainAssetsController_handleAccountAssetListUpdated, _MultichainAssetsController_isNonEvmAccount, _MultichainAssetsController_handleOnAccountAdded, _MultichainAssetsController_handleOnAccountRemovedEvent, _MultichainAssetsController_refreshAssetsMetadata, _MultichainAssetsController_updateAssetsMetadata, _MultichainAssetsController_getAssetSnaps, _MultichainAssetsController_getAssetSnapFor, _MultichainAssetsController_getAllSnaps, _MultichainAssetsController_getSnapsPermissions, _MultichainAssetsController_getAssetsMetadataFrom, _MultichainAssetsController_groupTokenAssetsByChain, _MultichainAssetsController_runBatchedBulkTokenScans, _MultichainAssetsController_filterBlockaidSpamTokensOnAdd, _MultichainAssetsController_findMaliciousTokensAmong, _MultichainAssetsController_getAssetsList, _MultichainAssetsController_getClient, _MultichainAssetsController_assertControllerMutexIsLocked, _MultichainAssetsController_withControllerLock;
13
+ var _MultichainAssetsController_instances, _MultichainAssetsController_snaps, _MultichainAssetsController_controllerOperationMutex, _MultichainAssetsController_handleAccountAssetListUpdatedEvent, _MultichainAssetsController_handleOnAccountAddedEvent, _MultichainAssetsController_isAssetIgnored, _MultichainAssetsController_handleAccountAssetListUpdated, _MultichainAssetsController_isNonEvmAccount, _MultichainAssetsController_handleOnAccountAdded, _MultichainAssetsController_bootstrapStellarTrustlineExtras, _MultichainAssetsController_handleAccountBalancesUpdatedForEnrichment, _MultichainAssetsController_enrichStellarAccountAssetInfo, _MultichainAssetsController_getAccountAssetInfoFromSnap, _MultichainAssetsController_handleOnAccountRemovedEvent, _MultichainAssetsController_refreshAssetsMetadata, _MultichainAssetsController_updateAssetsMetadata, _MultichainAssetsController_getAssetSnaps, _MultichainAssetsController_getAssetSnapFor, _MultichainAssetsController_getAllSnaps, _MultichainAssetsController_getSnapsPermissions, _MultichainAssetsController_getAssetsMetadataFrom, _MultichainAssetsController_groupTokenAssetsByChain, _MultichainAssetsController_runBatchedBulkTokenScans, _MultichainAssetsController_filterBlockaidSpamTokensOnAdd, _MultichainAssetsController_findMaliciousTokensAmong, _MultichainAssetsController_getAssetsList, _MultichainAssetsController_getClient, _MultichainAssetsController_assertControllerMutexIsLocked, _MultichainAssetsController_withControllerLock;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.MultichainAssetsController = exports.getDefaultMultichainAssetsControllerState = void 0;
16
16
  const keyring_api_1 = require("@metamask/keyring-api");
@@ -20,6 +20,7 @@ const polling_controller_1 = require("@metamask/polling-controller");
20
20
  const snaps_utils_1 = require("@metamask/snaps-utils");
21
21
  const utils_1 = require("@metamask/utils");
22
22
  const async_mutex_1 = require("async-mutex");
23
+ const stellarAccountAssetInfo_1 = require("../multichain/stellarAccountAssetInfo.cjs");
23
24
  const stellarTrustline_1 = require("../multichain/stellarTrustline.cjs");
24
25
  const utils_2 = require("./utils.cjs");
25
26
  const controllerName = 'MultichainAssetsController';
@@ -36,8 +37,6 @@ function getDefaultMultichainAssetsControllerState() {
36
37
  accountsAssets: {},
37
38
  assetsMetadata: {},
38
39
  allIgnoredAssets: {},
39
- stellarClassicTrustlineInactiveAssetIds: {},
40
- stellarTrustlineInactiveBackfillComplete: false,
41
40
  };
42
41
  }
43
42
  exports.getDefaultMultichainAssetsControllerState = getDefaultMultichainAssetsControllerState;
@@ -67,18 +66,6 @@ const assetsControllerMetadata = {
67
66
  includeInDebugSnapshot: false,
68
67
  usedInUi: true,
69
68
  },
70
- stellarClassicTrustlineInactiveAssetIds: {
71
- includeInStateLogs: false,
72
- persist: true,
73
- includeInDebugSnapshot: false,
74
- usedInUi: true,
75
- },
76
- stellarTrustlineInactiveBackfillComplete: {
77
- includeInStateLogs: false,
78
- persist: true,
79
- includeInDebugSnapshot: false,
80
- usedInUi: false,
81
- },
82
69
  };
83
70
  const MESSENGER_EXPOSED_METHODS = [
84
71
  'getAssetMetadata',
@@ -121,8 +108,30 @@ class MultichainAssetsController extends (0, polling_controller_1.StaticInterval
121
108
  this.messenger.subscribe('AccountsController:accountAssetListUpdated',
122
109
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
123
110
  async (event) => await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_handleAccountAssetListUpdatedEvent).call(this, event));
111
+ this.messenger.subscribe('AccountsController:accountBalancesUpdated', (event) => {
112
+ // eslint-disable-next-line no-void
113
+ void __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_handleAccountBalancesUpdatedForEnrichment).call(this, event);
114
+ });
115
+ // Bootstrap trust-line `extra` after unlock (and when already unlocked on first state event).
116
+ let previousKeyringIsUnlocked;
117
+ this.messenger.subscribe('KeyringController:stateChanged', (keyringState) => {
118
+ const { isUnlocked } = keyringState;
119
+ if (previousKeyringIsUnlocked === undefined) {
120
+ previousKeyringIsUnlocked = isUnlocked;
121
+ if (isUnlocked) {
122
+ // eslint-disable-next-line no-void
123
+ void __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_bootstrapStellarTrustlineExtras).call(this);
124
+ }
125
+ return;
126
+ }
127
+ const justUnlocked = isUnlocked && !previousKeyringIsUnlocked;
128
+ previousKeyringIsUnlocked = isUnlocked;
129
+ if (justUnlocked) {
130
+ // eslint-disable-next-line no-void
131
+ void __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_bootstrapStellarTrustlineExtras).call(this);
132
+ }
133
+ });
124
134
  messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
125
- __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_backfillStellarTrustlineInactiveIfNeeded).call(this);
126
135
  }
127
136
  async _executePoll(_input) {
128
137
  await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_withControllerLock).call(this, async () => {
@@ -178,7 +187,6 @@ class MultichainAssetsController extends (0, polling_controller_1.StaticInterval
178
187
  if (state.accountsAssets[accountId]) {
179
188
  state.accountsAssets[accountId] = state.accountsAssets[accountId].filter((asset) => !assetsToIgnore.includes(asset));
180
189
  }
181
- __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_removeStellarTrustlineInactiveAssetIds).call(this, state, accountId, assetsToIgnore);
182
190
  if (!state.allIgnoredAssets[accountId]) {
183
191
  state.allIgnoredAssets[accountId] = [];
184
192
  }
@@ -228,17 +236,6 @@ class MultichainAssetsController extends (0, polling_controller_1.StaticInterval
228
236
  delete state.allIgnoredAssets[accountId];
229
237
  }
230
238
  }
231
- for (const assetId of addedAssets) {
232
- if ((0, stellarTrustline_1.isStellarClassicAssetCaip19)(assetId)) {
233
- if (!state.stellarClassicTrustlineInactiveAssetIds[accountId]) {
234
- state.stellarClassicTrustlineInactiveAssetIds[accountId] = [];
235
- }
236
- const inactive = state.stellarClassicTrustlineInactiveAssetIds[accountId];
237
- if (!inactive.includes(assetId)) {
238
- inactive.push(assetId);
239
- }
240
- }
241
- }
242
239
  });
243
240
  // Publish event to notify other controllers (balances, rates) about the new assets
244
241
  if (addedAssets.length > 0) {
@@ -250,35 +247,16 @@ class MultichainAssetsController extends (0, polling_controller_1.StaticInterval
250
247
  },
251
248
  },
252
249
  });
250
+ // Let MultichainBalancesController create balance rows before merging trust-line `extra`.
251
+ await Promise.resolve();
252
+ await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_enrichStellarAccountAssetInfo).call(this, accountId, addedAssets);
253
253
  }
254
- await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_reconcileStellarClassicTrustlineInactiveWithSnap).call(this, accountId, addedAssets);
255
254
  return this.state.accountsAssets[accountId] || [];
256
255
  });
257
256
  }
258
257
  }
259
258
  exports.MultichainAssetsController = MultichainAssetsController;
260
- _MultichainAssetsController_snaps = new WeakMap(), _MultichainAssetsController_controllerOperationMutex = new WeakMap(), _MultichainAssetsController_instances = new WeakSet(), _MultichainAssetsController_backfillStellarTrustlineInactiveIfNeeded = function _MultichainAssetsController_backfillStellarTrustlineInactiveIfNeeded() {
261
- if (this.state.stellarTrustlineInactiveBackfillComplete) {
262
- return;
263
- }
264
- this.update((state) => {
265
- for (const [accountId, assets] of Object.entries(state.accountsAssets)) {
266
- for (const assetId of assets) {
267
- if (!(0, stellarTrustline_1.isStellarClassicAssetCaip19)(assetId)) {
268
- continue;
269
- }
270
- if (!state.stellarClassicTrustlineInactiveAssetIds[accountId]) {
271
- state.stellarClassicTrustlineInactiveAssetIds[accountId] = [];
272
- }
273
- const inactive = state.stellarClassicTrustlineInactiveAssetIds[accountId];
274
- if (!inactive.includes(assetId)) {
275
- inactive.push(assetId);
276
- }
277
- }
278
- }
279
- state.stellarTrustlineInactiveBackfillComplete = true;
280
- });
281
- }, _MultichainAssetsController_handleAccountAssetListUpdatedEvent =
259
+ _MultichainAssetsController_snaps = new WeakMap(), _MultichainAssetsController_controllerOperationMutex = new WeakMap(), _MultichainAssetsController_instances = new WeakSet(), _MultichainAssetsController_handleAccountAssetListUpdatedEvent =
282
260
  // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
283
261
  async function _MultichainAssetsController_handleAccountAssetListUpdatedEvent(event) {
284
262
  return __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_withControllerLock).call(this, async () => __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_handleAccountAssetListUpdated).call(this, event));
@@ -288,61 +266,6 @@ async function _MultichainAssetsController_handleOnAccountAddedEvent(account) {
288
266
  return __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_withControllerLock).call(this, async () => __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_handleOnAccountAdded).call(this, account));
289
267
  }, _MultichainAssetsController_isAssetIgnored = function _MultichainAssetsController_isAssetIgnored(asset, accountId) {
290
268
  return this.state.allIgnoredAssets[accountId]?.includes(asset) ?? false;
291
- }, _MultichainAssetsController_reconcileStellarClassicTrustlineInactiveWithSnap =
292
- /**
293
- * After `addAssets`, Stellar classic (`asset:`) ids are marked trustline-inactive until
294
- * the keyring confirms them. Re-fetch the account asset list from the Snap and clear
295
- * that flag for any added classic id the Snap already reports (e.g. hide → re-add with
296
- * an existing trustline), without relying on a later `accountAssetListUpdated` event.
297
- *
298
- * @param accountId - Account the assets were added to.
299
- * @param addedAssets - Assets that were newly added in this `addAssets` call.
300
- */
301
- async function _MultichainAssetsController_reconcileStellarClassicTrustlineInactiveWithSnap(accountId, addedAssets) {
302
- const stellarAdded = addedAssets.filter(stellarTrustline_1.isStellarClassicAssetCaip19);
303
- if (stellarAdded.length === 0) {
304
- return;
305
- }
306
- const accounts = this.messenger.call('AccountsController:listMultichainAccounts');
307
- const account = accounts.find((a) => a.id === accountId);
308
- if (!account || !__classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_isNonEvmAccount).call(this, account)) {
309
- return;
310
- }
311
- const snapId = account.metadata.snap?.id;
312
- if (!snapId) {
313
- return;
314
- }
315
- let snapAssets;
316
- try {
317
- snapAssets = await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_getAssetsList).call(this, accountId, snapId);
318
- }
319
- catch {
320
- return;
321
- }
322
- const snapAssetSet = new Set(snapAssets.filter(utils_1.isCaipAssetType));
323
- const confirmedTrustline = stellarAdded.filter((asset) => snapAssetSet.has(asset));
324
- if (confirmedTrustline.length === 0) {
325
- return;
326
- }
327
- this.update((state) => {
328
- __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_removeStellarTrustlineInactiveAssetIds).call(this, state, accountId, confirmedTrustline);
329
- });
330
- }, _MultichainAssetsController_removeStellarTrustlineInactiveAssetIds = function _MultichainAssetsController_removeStellarTrustlineInactiveAssetIds(state, accountId, assetIds) {
331
- if (assetIds.length === 0) {
332
- return;
333
- }
334
- const list = state.stellarClassicTrustlineInactiveAssetIds[accountId];
335
- if (!list) {
336
- return;
337
- }
338
- const drop = new Set(assetIds);
339
- const next = list.filter((a) => !drop.has(a));
340
- if (next.length === 0) {
341
- delete state.stellarClassicTrustlineInactiveAssetIds[accountId];
342
- }
343
- else {
344
- state.stellarClassicTrustlineInactiveAssetIds[accountId] = next;
345
- }
346
269
  }, _MultichainAssetsController_handleAccountAssetListUpdated =
347
270
  /**
348
271
  * Function to update the assets list for an account
@@ -354,11 +277,6 @@ async function _MultichainAssetsController_handleAccountAssetListUpdated(event)
354
277
  __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_assertControllerMutexIsLocked).call(this);
355
278
  const assetsForMetadataRefresh = new Set([]);
356
279
  const accountsAndAssetsToUpdate = {};
357
- /**
358
- * When the keyring re-announces a Stellar classic asset id the user had already
359
- * imported, `preFiltered` excludes it; we still clear "no trustline" UI state.
360
- */
361
- const clearStellarTrustlineInactiveByAccount = {};
362
280
  for (const [accountId, { added, removed }] of Object.entries(event.assets)) {
363
281
  if (added.length > 0 || removed.length > 0) {
364
282
  const existing = this.state.accountsAssets[accountId] || [];
@@ -369,15 +287,6 @@ async function _MultichainAssetsController_handleAccountAssetListUpdated(event)
369
287
  !__classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_isAssetIgnored).call(this, asset, accountId));
370
288
  // Filter out tokens that cannot be verified or are flagged malicious
371
289
  const filteredToBeAddedAssets = await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_filterBlockaidSpamTokensOnAdd).call(this, preFilteredToBeAddedAssets);
372
- const filteredToBeAddedSet = new Set(filteredToBeAddedAssets);
373
- const snapConfirmsStellarTrustline = added.filter((asset) => (0, utils_1.isCaipAssetType)(asset) &&
374
- !__classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_isAssetIgnored).call(this, asset, accountId) &&
375
- (0, stellarTrustline_1.isStellarClassicAssetCaip19)(asset) &&
376
- (existing.includes(asset) || filteredToBeAddedSet.has(asset)));
377
- if (snapConfirmsStellarTrustline.length > 0) {
378
- clearStellarTrustlineInactiveByAccount[accountId] =
379
- snapConfirmsStellarTrustline;
380
- }
381
290
  // In case accountsAndAssetsToUpdate event is fired with "removed" assets that don't exist, we don't want to remove them
382
291
  const filteredToBeRemovedAssets = removed.filter((asset) => existing.includes(asset) && (0, utils_1.isCaipAssetType)(asset));
383
292
  if (filteredToBeAddedAssets.length > 0 ||
@@ -398,28 +307,16 @@ async function _MultichainAssetsController_handleAccountAssetListUpdated(event)
398
307
  }
399
308
  }
400
309
  }
401
- const accountIdsToUpdate = new Set([
402
- ...Object.keys(accountsAndAssetsToUpdate),
403
- ...Object.keys(clearStellarTrustlineInactiveByAccount),
404
- ]);
405
310
  this.update((state) => {
406
- for (const accountId of accountIdsToUpdate) {
407
- const toMerge = accountsAndAssetsToUpdate[accountId];
408
- if (toMerge) {
409
- const { added, removed: removedAssets } = toMerge;
410
- const assets = new Set([
411
- ...(state.accountsAssets[accountId] || []),
412
- ...added,
413
- ]);
414
- for (const asset of removedAssets) {
415
- assets.delete(asset);
416
- }
417
- state.accountsAssets[accountId] = Array.from(assets);
418
- }
419
- __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_removeStellarTrustlineInactiveAssetIds).call(this, state, accountId, clearStellarTrustlineInactiveByAccount[accountId] ?? []);
420
- if (toMerge) {
421
- __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_removeStellarTrustlineInactiveAssetIds).call(this, state, accountId, toMerge.removed);
311
+ for (const [accountId, { added, removed: removedAssets }] of Object.entries(accountsAndAssetsToUpdate)) {
312
+ const assets = new Set([
313
+ ...(state.accountsAssets[accountId] || []),
314
+ ...added,
315
+ ]);
316
+ for (const asset of removedAssets) {
317
+ assets.delete(asset);
422
318
  }
319
+ state.accountsAssets[accountId] = Array.from(assets);
423
320
  }
424
321
  });
425
322
  // Trigger fetching metadata for new assets
@@ -453,7 +350,6 @@ async function _MultichainAssetsController_handleOnAccountAdded(account) {
453
350
  await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_refreshAssetsMetadata).call(this, assets);
454
351
  this.update((state) => {
455
352
  state.accountsAssets[account.id] = assets;
456
- delete state.stellarClassicTrustlineInactiveAssetIds[account.id];
457
353
  });
458
354
  this.messenger.publish(`${controllerName}:accountAssetListUpdated`, {
459
355
  assets: {
@@ -463,6 +359,126 @@ async function _MultichainAssetsController_handleOnAccountAdded(account) {
463
359
  },
464
360
  },
465
361
  });
362
+ await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_enrichStellarAccountAssetInfo).call(this, account.id, filteredCaip);
363
+ }
364
+ }, _MultichainAssetsController_bootstrapStellarTrustlineExtras =
365
+ /**
366
+ * After unlock, enrich trust-line `extra` for all Stellar classics already in the portfolio.
367
+ */
368
+ async function _MultichainAssetsController_bootstrapStellarTrustlineExtras() {
369
+ const { isUnlocked } = this.messenger.call('KeyringController:getState');
370
+ if (!isUnlocked) {
371
+ return;
372
+ }
373
+ const accounts = this.messenger.call('AccountsController:listMultichainAccounts');
374
+ for (const account of accounts) {
375
+ if (!(0, stellarAccountAssetInfo_1.isStellarMultichainAccount)(account)) {
376
+ continue;
377
+ }
378
+ const classics = (this.state.accountsAssets[account.id] ?? []).filter(stellarTrustline_1.isStellarClassicAssetCaip19);
379
+ if (classics.length > 0) {
380
+ await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_enrichStellarAccountAssetInfo).call(this, account.id, classics);
381
+ }
382
+ }
383
+ }, _MultichainAssetsController_handleAccountBalancesUpdatedForEnrichment =
384
+ /**
385
+ * After snap balance events, fetch Stellar asset info (metadata + trust-line `extra`).
386
+ *
387
+ * @param payload - Keyring balance update payload.
388
+ */
389
+ async function _MultichainAssetsController_handleAccountBalancesUpdatedForEnrichment(payload) {
390
+ // Yield so MultichainBalancesController applies balance rows first (MAC inits before MBC in extension).
391
+ await Promise.resolve();
392
+ for (const accountId of Object.keys(payload.balances)) {
393
+ const classics = (this.state.accountsAssets[accountId] ?? []).filter(stellarTrustline_1.isStellarClassicAssetCaip19);
394
+ if (classics.length === 0) {
395
+ continue;
396
+ }
397
+ await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_enrichStellarAccountAssetInfo).call(this, accountId, classics);
398
+ }
399
+ }, _MultichainAssetsController_enrichStellarAccountAssetInfo =
400
+ /**
401
+ * Fetches Stellar-only `keyring_getAccountAssetInfo` and merges metadata + balance `extra`.
402
+ *
403
+ * @param accountId - Account id.
404
+ * @param assetIds - Assets to enrich.
405
+ */
406
+ async function _MultichainAssetsController_enrichStellarAccountAssetInfo(accountId, assetIds) {
407
+ const stellarClassicIds = assetIds.filter(stellarTrustline_1.isStellarClassicAssetCaip19);
408
+ if (stellarClassicIds.length === 0) {
409
+ return;
410
+ }
411
+ const accounts = this.messenger.call('AccountsController:listMultichainAccounts');
412
+ const account = accounts.find((a) => a.id === accountId);
413
+ if (!account || !(0, stellarAccountAssetInfo_1.isStellarMultichainAccount)(account)) {
414
+ return;
415
+ }
416
+ const snapId = account.metadata.snap?.id;
417
+ if (!snapId) {
418
+ return;
419
+ }
420
+ const info = await __classPrivateFieldGet(this, _MultichainAssetsController_instances, "m", _MultichainAssetsController_getAccountAssetInfoFromSnap).call(this, accountId, snapId, stellarClassicIds);
421
+ if (!info) {
422
+ return;
423
+ }
424
+ const metadataUpdates = {};
425
+ const extrasByAsset = {};
426
+ for (const assetId of stellarClassicIds) {
427
+ const entry = info[assetId];
428
+ if (!entry) {
429
+ // Snap omits assets with no on-chain row (portfolio import without trust line).
430
+ extrasByAsset[assetId] = { limit: '0' };
431
+ continue;
432
+ }
433
+ metadataUpdates[assetId] = entry.metadata;
434
+ const balanceExtra = (0, stellarAccountAssetInfo_1.stellarAssetInfoExtraToBalanceExtra)(entry.extra);
435
+ if (balanceExtra === undefined) {
436
+ // Snap omits extra when there is no on-chain trust line (portfolio import).
437
+ extrasByAsset[assetId] = { limit: '0' };
438
+ }
439
+ else {
440
+ extrasByAsset[assetId] = balanceExtra;
441
+ }
442
+ }
443
+ if (Object.keys(metadataUpdates).length > 0) {
444
+ this.update((state) => {
445
+ state.assetsMetadata = {
446
+ ...state.assetsMetadata,
447
+ ...metadataUpdates,
448
+ };
449
+ });
450
+ }
451
+ if (Object.keys(extrasByAsset).length > 0) {
452
+ this.messenger.call('MultichainBalancesController:mergeAccountBalanceExtras', accountId, extrasByAsset);
453
+ }
454
+ }, _MultichainAssetsController_getAccountAssetInfoFromSnap =
455
+ /**
456
+ * Calls the Stellar snap `keyring_getAccountAssetInfo` handler.
457
+ *
458
+ * @param accountId - Account id.
459
+ * @param snapId - Stellar wallet snap id.
460
+ * @param assets - CAIP-19 assets to resolve.
461
+ * @returns Per-asset metadata and optional trust-line extra, or undefined on failure.
462
+ */
463
+ async function _MultichainAssetsController_getAccountAssetInfoFromSnap(accountId, snapId, assets) {
464
+ try {
465
+ return (await this.messenger.call('SnapController:handleRequest', {
466
+ snapId: snapId,
467
+ origin: 'metamask',
468
+ handler: snaps_utils_1.HandlerType.OnKeyringRequest,
469
+ request: {
470
+ jsonrpc: '2.0',
471
+ method: stellarAccountAssetInfo_1.KEYRING_GET_ACCOUNT_ASSET_INFO_METHOD,
472
+ params: {
473
+ accountId,
474
+ assets,
475
+ },
476
+ },
477
+ }));
478
+ }
479
+ catch (error) {
480
+ console.error(error);
481
+ return undefined;
466
482
  }
467
483
  }, _MultichainAssetsController_handleOnAccountRemovedEvent =
468
484
  /**
@@ -478,9 +494,6 @@ async function _MultichainAssetsController_handleOnAccountRemovedEvent(accountId
478
494
  if (state.allIgnoredAssets[accountId]) {
479
495
  delete state.allIgnoredAssets[accountId];
480
496
  }
481
- if (state.stellarClassicTrustlineInactiveAssetIds[accountId]) {
482
- delete state.stellarClassicTrustlineInactiveAssetIds[accountId];
483
- }
484
497
  // TODO: We are not deleting the assetsMetadata because we will soon make this controller extends StaticIntervalPollingController
485
498
  // and update all assetsMetadata once a day.
486
499
  });