@metamask/assets-controller 9.0.1 → 9.1.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +43 -2
  2. package/dist/AssetsController.cjs +25 -15
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts.map +1 -1
  5. package/dist/AssetsController.d.mts.map +1 -1
  6. package/dist/AssetsController.mjs +25 -15
  7. package/dist/AssetsController.mjs.map +1 -1
  8. package/dist/data-sources/AccountsApiDataSource.cjs +1 -1
  9. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
  10. package/dist/data-sources/AccountsApiDataSource.mjs +1 -1
  11. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
  12. package/dist/data-sources/PriceDataSource.cjs +64 -13
  13. package/dist/data-sources/PriceDataSource.cjs.map +1 -1
  14. package/dist/data-sources/PriceDataSource.d.cts +13 -0
  15. package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
  16. package/dist/data-sources/PriceDataSource.d.mts +13 -0
  17. package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
  18. package/dist/data-sources/PriceDataSource.mjs +64 -13
  19. package/dist/data-sources/PriceDataSource.mjs.map +1 -1
  20. package/dist/data-sources/SnapDataSource.cjs +2 -2
  21. package/dist/data-sources/SnapDataSource.cjs.map +1 -1
  22. package/dist/data-sources/SnapDataSource.mjs +2 -2
  23. package/dist/data-sources/SnapDataSource.mjs.map +1 -1
  24. package/dist/index.cjs +3 -1
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +2 -2
  27. package/dist/index.d.cts.map +1 -1
  28. package/dist/index.d.mts +2 -2
  29. package/dist/index.d.mts.map +1 -1
  30. package/dist/index.mjs +1 -1
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/middlewares/DetectionMiddleware.cjs +43 -23
  33. package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
  34. package/dist/middlewares/DetectionMiddleware.d.cts +12 -13
  35. package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
  36. package/dist/middlewares/DetectionMiddleware.d.mts +12 -13
  37. package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
  38. package/dist/middlewares/DetectionMiddleware.mjs +43 -23
  39. package/dist/middlewares/DetectionMiddleware.mjs.map +1 -1
  40. package/dist/selectors/balance.cjs +191 -8
  41. package/dist/selectors/balance.cjs.map +1 -1
  42. package/dist/selectors/balance.d.cts +80 -0
  43. package/dist/selectors/balance.d.cts.map +1 -1
  44. package/dist/selectors/balance.d.mts +80 -0
  45. package/dist/selectors/balance.d.mts.map +1 -1
  46. package/dist/selectors/balance.mjs +186 -7
  47. package/dist/selectors/balance.mjs.map +1 -1
  48. package/dist/utils/dedupingBatchFetcher.cjs +157 -0
  49. package/dist/utils/dedupingBatchFetcher.cjs.map +1 -0
  50. package/dist/utils/dedupingBatchFetcher.d.cts +65 -0
  51. package/dist/utils/dedupingBatchFetcher.d.cts.map +1 -0
  52. package/dist/utils/dedupingBatchFetcher.d.mts +65 -0
  53. package/dist/utils/dedupingBatchFetcher.d.mts.map +1 -0
  54. package/dist/utils/dedupingBatchFetcher.mjs +153 -0
  55. package/dist/utils/dedupingBatchFetcher.mjs.map +1 -0
  56. package/package.json +12 -12
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getAggregatedBalanceForAccount = exports.getInternalAccountsForGroup = exports.getGroupIdForAccount = void 0;
6
+ exports.calculateBalanceChangeForAccountGroup = exports.calculateBalanceForAllWallets = exports.getAggregatedBalanceForAccount = exports.getAggregatedBalanceForAccountIds = exports.getAccountIdsForGroup = exports.getInternalAccountsForGroup = exports.getGroupIdForAccount = void 0;
7
7
  const controller_utils_1 = require("@metamask/controller-utils");
8
8
  const utils_1 = require("@metamask/utils");
9
9
  const bignumber_js_1 = __importDefault(require("bignumber.js"));
@@ -238,7 +238,43 @@ function resolveAccountsToAggregate(args) {
238
238
  }
239
239
  return [selectedInternalAccount];
240
240
  }
241
- function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledNetworkMap, accountTreeState, internalAccountsOrAccountIds, accountsById, trace) {
241
+ /**
242
+ * Get account ids that belong to a group, reading directly from the account
243
+ * tree. Unlike {@link getInternalAccountsForGroup}, this does not require an
244
+ * `accountsById` lookup map, which makes it convenient for balance aggregation
245
+ * where only the ids are needed.
246
+ *
247
+ * @param accountTreeState - AccountTreeController state.
248
+ * @param groupId - The account group id to look up.
249
+ * @returns The list of account ids in the group, or an empty array.
250
+ */
251
+ function getAccountIdsForGroup(accountTreeState, groupId) {
252
+ const wallets = accountTreeState.accountTree?.wallets ?? {};
253
+ for (const wallet of Object.values(wallets)) {
254
+ const groups = (wallet?.groups ?? {});
255
+ const group = groups[groupId];
256
+ if (group?.accounts) {
257
+ return [...group.accounts];
258
+ }
259
+ }
260
+ return [];
261
+ }
262
+ exports.getAccountIdsForGroup = getAccountIdsForGroup;
263
+ /**
264
+ * Aggregate balances across an explicit list of accounts.
265
+ *
266
+ * This is the core aggregation engine shared by the account- and group-level
267
+ * selectors. It intentionally takes a fully-resolved list of accounts so that
268
+ * callers control account resolution and no "selected account" placeholder is
269
+ * required.
270
+ *
271
+ * @param state - AssetsController state slice.
272
+ * @param accounts - Accounts whose balances should be aggregated.
273
+ * @param enabledNetworkMap - Optional map of enabled networks keyed by namespace.
274
+ * @param trace - Optional trace callback for telemetry spans.
275
+ * @returns Aggregated balance entries plus fiat totals when prices are present.
276
+ */
277
+ function aggregateBalances(state, accounts, enabledNetworkMap, trace) {
242
278
  const startTime = trace ? performance.now() : 0;
243
279
  const { assetsBalance, assetsInfo, assetPreferences, assetsPrice } = state;
244
280
  const metadata = (assetsInfo ?? {});
@@ -251,12 +287,7 @@ function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledN
251
287
  }
252
288
  return false;
253
289
  })();
254
- const accountsToAggregate = resolveAccountsToAggregate({
255
- selectedInternalAccount,
256
- accountTreeState,
257
- internalAccountsOrAccountIds,
258
- accountsById,
259
- });
290
+ const accountsToAggregate = accounts;
260
291
  const assetInfoCache = makeAssetInfoCache();
261
292
  const merged = new Map();
262
293
  for (const account of accountsToAggregate) {
@@ -276,6 +307,7 @@ function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledN
276
307
  let idx = 0;
277
308
  // If prices exist, compute totals in a single pass over merged.
278
309
  let totalBalanceInFiat = 0;
310
+ let previousTotalInFiat = 0;
279
311
  let weightedNumerator = 0;
280
312
  for (const [assetId, row] of merged.entries()) {
281
313
  const { amount } = row;
@@ -294,6 +326,11 @@ function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledN
294
326
  if (contribution > 0) {
295
327
  totalBalanceInFiat += contribution;
296
328
  weightedNumerator += contribution * pricePercentChange1d;
329
+ // A -100% move makes the denominator zero; treat it as flat so the
330
+ // previous total never goes to infinity.
331
+ const denom = Number((1 + pricePercentChange1d / 100).toFixed(8));
332
+ previousTotalInFiat +=
333
+ denom === 0 ? contribution : contribution / denom;
297
334
  }
298
335
  }
299
336
  }
@@ -323,9 +360,155 @@ function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledN
323
360
  entries,
324
361
  totalBalanceInFiat,
325
362
  pricePercentChange1d,
363
+ previousTotalInFiat,
326
364
  };
327
365
  }
328
366
  return { entries };
329
367
  }
368
+ /**
369
+ * Aggregate balances for an explicit list of account ids.
370
+ *
371
+ * Prefer this over {@link getAggregatedBalanceForAccount} when the set of
372
+ * accounts to aggregate is already known (e.g. all accounts in a group), since
373
+ * it does not require a "selected account" and therefore avoids the brittle
374
+ * account-resolution heuristics.
375
+ *
376
+ * @param state - AssetsController state slice.
377
+ * @param accountIds - Account ids whose balances should be aggregated.
378
+ * @param enabledNetworkMap - Optional map of enabled networks keyed by namespace.
379
+ * @param trace - Optional trace callback for telemetry spans.
380
+ * @returns Aggregated balance entries plus fiat totals when prices are present.
381
+ */
382
+ function getAggregatedBalanceForAccountIds(state, accountIds, enabledNetworkMap, trace) {
383
+ const accounts = accountIds.map((id) => ({ id }));
384
+ return aggregateBalances(state, accounts, enabledNetworkMap, trace);
385
+ }
386
+ exports.getAggregatedBalanceForAccountIds = getAggregatedBalanceForAccountIds;
387
+ function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledNetworkMap, accountTreeState, internalAccountsOrAccountIds, accountsById, trace) {
388
+ const accountsToAggregate = resolveAccountsToAggregate({
389
+ selectedInternalAccount,
390
+ accountTreeState,
391
+ internalAccountsOrAccountIds,
392
+ accountsById,
393
+ });
394
+ return aggregateBalances(state, accountsToAggregate, enabledNetworkMap, trace);
395
+ }
330
396
  exports.getAggregatedBalanceForAccount = getAggregatedBalanceForAccount;
397
+ // ============================================================================
398
+ // WALLET- AND GROUP-LEVEL BALANCE CALCULATIONS
399
+ // ============================================================================
400
+ /**
401
+ * Default user currency used when {@link AssetsControllerState.selectedCurrency}
402
+ * is not set.
403
+ */
404
+ const DEFAULT_USER_CURRENCY = 'usd';
405
+ /**
406
+ * Resolve the user currency for a balance calculation, falling back to a
407
+ * sensible default when the controller has no selected currency.
408
+ *
409
+ * @param assetsControllerState - AssetsController state slice.
410
+ * @returns The user currency code.
411
+ */
412
+ function getUserCurrency(assetsControllerState) {
413
+ return assetsControllerState.selectedCurrency ?? DEFAULT_USER_CURRENCY;
414
+ }
415
+ /**
416
+ * Resolve the current and previous totals for a change calculation.
417
+ *
418
+ * The AssetsController state only exposes a 1d price change, so non-`1d`
419
+ * periods produce a zeroed change (previous equals current).
420
+ *
421
+ * @param totalBalanceInFiat - Aggregated current balance in user currency.
422
+ * @param previousTotalInFiat - Aggregated prior balance summed per asset.
423
+ * @param period - Period to compute the change for.
424
+ * @returns The current and previous totals in user currency.
425
+ */
426
+ function getCurrentAndPrevious(totalBalanceInFiat, previousTotalInFiat, period) {
427
+ const current = totalBalanceInFiat;
428
+ const previous = period === '1d' ? previousTotalInFiat : current;
429
+ return { current, previous };
430
+ }
431
+ /**
432
+ * Build a {@link BalanceChangeResult} from current/previous totals.
433
+ *
434
+ * @param current - Current total in user currency.
435
+ * @param previous - Previous total in user currency.
436
+ * @param period - Period the change was computed for.
437
+ * @param userCurrency - User currency code.
438
+ * @returns The change result with delta and percent change.
439
+ */
440
+ function buildBalanceChangeResult(current, previous, period, userCurrency) {
441
+ const amountChange = current - previous;
442
+ const percentChange = previous === 0 ? 0 : (amountChange / previous) * 100;
443
+ return {
444
+ period,
445
+ currentTotalInUserCurrency: Number(current.toFixed(8)),
446
+ previousTotalInUserCurrency: Number(previous.toFixed(8)),
447
+ amountChangeInUserCurrency: Number(amountChange.toFixed(8)),
448
+ percentChange: Number(percentChange.toFixed(8)),
449
+ userCurrency,
450
+ };
451
+ }
452
+ /**
453
+ * Calculate aggregated balances for all wallets and groups.
454
+ *
455
+ * Mirrors the legacy `@metamask/assets-controllers` `calculateBalanceForAllWallets`
456
+ * output shape, but sources every group total from the unified AssetsController
457
+ * state via {@link getAggregatedBalanceForAccountIds}. The account tree is walked
458
+ * to aggregate each group individually.
459
+ *
460
+ * @param assetsControllerState - AssetsController state slice.
461
+ * @param accountTreeState - AccountTreeController state.
462
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
463
+ * @param trace - Optional trace callback forwarded to the aggregation selector.
464
+ * @returns Aggregated balances for all wallets and groups.
465
+ */
466
+ function calculateBalanceForAllWallets(assetsControllerState, accountTreeState, enabledNetworkMap, trace) {
467
+ const userCurrency = getUserCurrency(assetsControllerState);
468
+ const wallets = {};
469
+ let totalBalanceInUserCurrency = 0;
470
+ for (const [walletId, wallet] of Object.entries(accountTreeState.accountTree?.wallets ?? {})) {
471
+ const walletBalance = {
472
+ walletId,
473
+ groups: {},
474
+ totalBalanceInUserCurrency: 0,
475
+ userCurrency,
476
+ };
477
+ const groups = wallet?.groups ?? {};
478
+ for (const groupId of Object.keys(groups)) {
479
+ const accountIds = getAccountIdsForGroup(accountTreeState, groupId);
480
+ const { totalBalanceInFiat = 0 } = getAggregatedBalanceForAccountIds(assetsControllerState, accountIds, enabledNetworkMap, trace);
481
+ walletBalance.groups[groupId] = {
482
+ walletId,
483
+ groupId,
484
+ totalBalanceInUserCurrency: totalBalanceInFiat,
485
+ userCurrency,
486
+ };
487
+ walletBalance.totalBalanceInUserCurrency += totalBalanceInFiat;
488
+ }
489
+ wallets[walletId] = walletBalance;
490
+ totalBalanceInUserCurrency += walletBalance.totalBalanceInUserCurrency;
491
+ }
492
+ return { wallets, totalBalanceInUserCurrency, userCurrency };
493
+ }
494
+ exports.calculateBalanceForAllWallets = calculateBalanceForAllWallets;
495
+ /**
496
+ * Calculate the portfolio value change for a single account group and period.
497
+ *
498
+ * @param assetsControllerState - AssetsController state slice.
499
+ * @param accountTreeState - AccountTreeController state.
500
+ * @param groupId - Account group id to compute the change for.
501
+ * @param period - Change period (`1d` | `7d` | `30d`).
502
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
503
+ * @param trace - Optional trace callback forwarded to the aggregation selector.
504
+ * @returns The change result for the requested period.
505
+ */
506
+ function calculateBalanceChangeForAccountGroup(assetsControllerState, accountTreeState, groupId, period, enabledNetworkMap, trace) {
507
+ const userCurrency = getUserCurrency(assetsControllerState);
508
+ const accountIds = getAccountIdsForGroup(accountTreeState, groupId);
509
+ const { totalBalanceInFiat = 0, previousTotalInFiat = totalBalanceInFiat } = getAggregatedBalanceForAccountIds(assetsControllerState, accountIds, enabledNetworkMap, trace);
510
+ const { current, previous } = getCurrentAndPrevious(totalBalanceInFiat, previousTotalInFiat, period);
511
+ return buildBalanceChangeResult(current, previous, period, userCurrency);
512
+ }
513
+ exports.calculateBalanceChangeForAccountGroup = calculateBalanceChangeForAccountGroup;
331
514
  //# sourceMappingURL=balance.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"balance.cjs","sourceRoot":"","sources":["../../src/selectors/balance.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountTreeControllerState } from '@metamask/account-tree-controller';\nimport { toHex } from '@metamask/controller-utils';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { CaipChainId, Hex } from '@metamask/utils';\nimport {\n KnownCaipNamespace,\n isStrictHexString,\n parseCaipAssetType,\n parseCaipChainId,\n} from '@metamask/utils';\nimport BigNumberJS from 'bignumber.js';\n\nimport type { AssetsControllerState } from '../AssetsController';\nimport type {\n AccountId,\n AssetBalance,\n AssetMetadata,\n AssetPreferences,\n Caip19AssetId,\n} from '../types';\n\n// ============================================================================\n// TRACE NAMES — used in Sentry spans (search these strings in Discover)\n// ============================================================================\nconst TRACE_AGGREGATED_BALANCE_SELECTOR = 'AggregatedBalanceSelector';\n\nexport type EnabledNetworkMap =\n | Record<string, Record<string, boolean>>\n | undefined;\n\nexport type AggregatedBalanceEntry = {\n assetId: Caip19AssetId;\n amount: string;\n decimals?: number;\n symbol?: string;\n name?: string;\n};\n\nexport type AggregatedBalanceForAccount = {\n entries: AggregatedBalanceEntry[];\n totalBalanceInFiat?: number;\n pricePercentChange1d?: number;\n};\n\ntype AccountLike = { id: AccountId };\nexport type AccountsById = Record<AccountId, InternalAccount>;\n\ntype PriceDatum = { price: number; pricePercentChange1d: number };\n\nconst ZERO_PRICE: PriceDatum = { price: 0, pricePercentChange1d: 0 };\n\nconst getAmountFromBalance = (balance: AssetBalance): string => {\n if (typeof balance === 'object' && balance !== null && 'amount' in balance) {\n const { amount } = balance as { amount?: unknown };\n return typeof amount === 'string' ? amount : '0';\n }\n return '0';\n};\n\nconst toBigNumberOrZero = (value: string): BigNumberJS => {\n const parsed = new BigNumberJS(value);\n return parsed.isNaN() || !parsed.isFinite() ? new BigNumberJS(0) : parsed;\n};\n\n/**\n * When state contains raw base units (e.g. SPORE \"16201541034.639288184\" with 9 decimals),\n * scale to human (16.2) before pricing. Only scale when amount >= 10^decimals so we don't\n * double-scale amounts that are already human (e.g. \"1\", \"0.227285\").\n *\n * @param amountRaw - Amount from state (may be raw or human).\n * @param decimals - Token decimals from metadata.\n * @returns Human amount for display and fiat (amountRaw or amountRaw / 10^decimals).\n */\nconst scaleToHumanIfRaw = (\n amountRaw: BigNumberJS,\n decimals: number,\n): BigNumberJS => {\n if (decimals <= 0) {\n return amountRaw;\n }\n const scale = new BigNumberJS(10).pow(decimals);\n if (amountRaw.lt(scale)) {\n return amountRaw;\n }\n return amountRaw.dividedBy(scale);\n};\n\nconst getPriceDatumFast = (\n assetsPrice: AssetsControllerState['assetsPrice'] | undefined,\n assetId: Caip19AssetId,\n): PriceDatum => {\n const raw = assetsPrice?.[assetId];\n if (!raw || typeof raw !== 'object') {\n return ZERO_PRICE;\n }\n const { price, pricePercentChange1d } = raw as {\n price?: unknown;\n pricePercentChange1d?: unknown;\n };\n return {\n price: typeof price === 'number' && Number.isFinite(price) ? price : 0,\n pricePercentChange1d:\n typeof pricePercentChange1d === 'number' &&\n Number.isFinite(pricePercentChange1d)\n ? pricePercentChange1d\n : 0,\n };\n};\n\n/**\n * Enablement lookup optimized:\n * - no array allocations\n * - early returns\n *\n * @param map - Enabled network map (namespace -> storageKey -> boolean)\n * @param id - Chain id as Hex or CAIP-2\n * @returns True if the chain is enabled or map is undefined\n */\nconst isChainEnabledByMap = (\n map: EnabledNetworkMap,\n id: Hex | CaipChainId,\n): boolean => {\n if (!map) {\n return true;\n }\n\n if (isStrictHexString(id)) {\n return Boolean(map[KnownCaipNamespace.Eip155]?.[id]);\n }\n\n const { namespace, reference } = parseCaipChainId(id);\n const namespaceMap = map[namespace];\n if (!namespaceMap) {\n return false;\n }\n\n // exact CAIP-2 id / reference\n if (namespaceMap[id] || namespaceMap[reference]) {\n return true;\n }\n\n // EVM: hex storage key\n if (namespace === KnownCaipNamespace.Eip155) {\n try {\n const storageKey = toHex(reference);\n return Boolean(namespaceMap[storageKey]);\n } catch {\n const parsedRef = Number.parseInt(reference, 10);\n if (Number.isFinite(parsedRef)) {\n return Boolean(namespaceMap[`0x${parsedRef.toString(16)}`]);\n }\n }\n }\n\n return false;\n};\n\n/**\n * Cache parsing results per assetId to avoid parseCaipAssetType/parseCaipChainId\n * being called multiple times across filtering + grouping + pricing.\n */\ntype AssetParseInfo = {\n chainId: CaipChainId;\n isEvm: boolean;\n};\n\nconst makeAssetInfoCache = (): Map<Caip19AssetId, AssetParseInfo> =>\n new Map<Caip19AssetId, AssetParseInfo>();\n\nconst getAssetInfo = (\n cache: Map<Caip19AssetId, AssetParseInfo>,\n assetId: Caip19AssetId,\n): AssetParseInfo => {\n const cached = cache.get(assetId);\n if (cached) {\n return cached;\n }\n const { chainId } = parseCaipAssetType(assetId);\n const { namespace } = parseCaipChainId(chainId);\n const info = { chainId, isEvm: namespace === KnownCaipNamespace.Eip155 };\n cache.set(assetId, info);\n return info;\n};\n\n/**\n * Merge across accounts without building per-account entries arrays.\n * Uses BigNumber for amount accumulation to avoid float precision loss.\n */\ntype AggRow = {\n amount: BigNumberJS;\n decimals?: number;\n symbol?: string;\n name?: string;\n};\n\nfunction mergeBalancesIntoMap(args: {\n out: Map<Caip19AssetId, AggRow>;\n accountBalances: Record<Caip19AssetId, AssetBalance>;\n metadata: Record<Caip19AssetId, AssetMetadata>;\n assetPreferences?: Record<Caip19AssetId, AssetPreferences>;\n enabledNetworkMap?: EnabledNetworkMap;\n assetInfoCache: Map<Caip19AssetId, AssetParseInfo>;\n}): void {\n const {\n out,\n accountBalances,\n metadata,\n assetPreferences,\n enabledNetworkMap,\n assetInfoCache,\n } = args;\n\n for (const assetId in accountBalances) {\n if (!Object.prototype.hasOwnProperty.call(accountBalances, assetId)) {\n continue;\n }\n const typedAssetId = assetId as Caip19AssetId;\n\n if (assetPreferences?.[typedAssetId]?.hidden) {\n continue;\n }\n\n const info = getAssetInfo(assetInfoCache, typedAssetId);\n if (!isChainEnabledByMap(enabledNetworkMap, info.chainId)) {\n continue;\n }\n\n const amountStr = getAmountFromBalance(accountBalances[typedAssetId]);\n let amountBn = toBigNumberOrZero(amountStr);\n const meta = metadata[typedAssetId];\n if (meta?.decimals !== undefined) {\n amountBn = scaleToHumanIfRaw(amountBn, meta.decimals);\n }\n if (amountBn.isZero()) {\n continue; // skip zeros early to reduce map pressure\n }\n\n const existing = out.get(typedAssetId);\n if (existing) {\n existing.amount = existing.amount.plus(amountBn);\n continue;\n }\n\n out.set(typedAssetId, {\n amount: amountBn,\n decimals: meta?.decimals,\n symbol: meta?.symbol,\n name: meta?.name,\n });\n }\n}\n\nexport function getGroupIdForAccount(\n accountTreeState: AccountTreeControllerState,\n accountId: AccountId,\n): string | undefined {\n const wallets = accountTreeState.accountTree?.wallets;\n if (!wallets) {\n return undefined;\n }\n for (const wallet of Object.values(wallets)) {\n for (const [groupId, group] of Object.entries(wallet?.groups ?? {})) {\n const accounts = group?.accounts;\n if (Array.isArray(accounts) && accounts.includes(accountId)) {\n return groupId;\n }\n }\n }\n return undefined;\n}\n\nexport function getInternalAccountsForGroup(\n accountTreeState: AccountTreeControllerState,\n accountsById: AccountsById,\n groupId: string,\n): InternalAccount[] {\n const wallets = accountTreeState.accountTree?.wallets;\n if (!wallets) {\n return [];\n }\n type GroupWithAccounts = { accounts?: AccountId[] };\n const getGroups = (\n walletItem: (typeof wallets)[keyof typeof wallets],\n ): Record<string, GroupWithAccounts> =>\n (walletItem?.groups ?? {}) as Record<string, GroupWithAccounts>;\n\n for (const wallet of Object.values(wallets)) {\n const group = getGroups(wallet)[groupId];\n if (!group?.accounts) {\n continue;\n }\n const result: InternalAccount[] = [];\n for (const id of group.accounts) {\n const acct = accountsById[id];\n if (acct) {\n result.push(acct);\n }\n }\n return result;\n }\n return [];\n}\n\nfunction getAccountIdsInSameGroup(\n accountTreeState: AccountTreeControllerState,\n selectedAccountId: AccountId,\n): AccountId[] | undefined {\n const groupId = getGroupIdForAccount(accountTreeState, selectedAccountId);\n if (!groupId) {\n return undefined;\n }\n const wallets = accountTreeState.accountTree?.wallets;\n if (!wallets) {\n return undefined;\n }\n type GroupWithAccounts = { accounts?: AccountId[] };\n const getGroups = (\n walletItem: (typeof wallets)[keyof typeof wallets],\n ): Record<string, GroupWithAccounts> =>\n (walletItem?.groups ?? {}) as Record<string, GroupWithAccounts>;\n\n for (const wallet of Object.values(wallets)) {\n const group = getGroups(wallet)[groupId];\n if (group?.accounts) {\n return [...group.accounts];\n }\n }\n return undefined;\n}\n\nfunction resolveAccountsToAggregate(args: {\n selectedInternalAccount: InternalAccount;\n accountTreeState?: AccountTreeControllerState;\n internalAccountsOrAccountIds?: InternalAccount[] | AccountId[];\n accountsById?: AccountsById;\n}): AccountLike[] {\n const {\n selectedInternalAccount,\n accountTreeState,\n internalAccountsOrAccountIds,\n accountsById,\n } = args;\n\n if (internalAccountsOrAccountIds && internalAccountsOrAccountIds.length > 0) {\n const first = internalAccountsOrAccountIds[0];\n if (typeof first === 'string') {\n const ids = internalAccountsOrAccountIds as AccountId[];\n const out: AccountLike[] = new Array(ids.length);\n for (let i = 0; i < ids.length; i++) {\n out[i] = { id: ids[i] };\n }\n return out;\n }\n return internalAccountsOrAccountIds as InternalAccount[];\n }\n\n if (\n accountTreeState &&\n accountsById &&\n Object.keys(accountsById).length > 0\n ) {\n const groupId = getGroupIdForAccount(\n accountTreeState,\n selectedInternalAccount.id,\n );\n if (groupId) {\n const groupAccounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsById,\n groupId,\n );\n if (groupAccounts.length > 0) {\n return groupAccounts;\n }\n }\n }\n\n if (accountTreeState) {\n const ids = getAccountIdsInSameGroup(\n accountTreeState,\n selectedInternalAccount.id,\n );\n if (ids && ids.length > 0) {\n const out: AccountLike[] = new Array(ids.length);\n for (let i = 0; i < ids.length; i++) {\n out[i] = { id: ids[i] };\n }\n return out;\n }\n }\n\n return [selectedInternalAccount];\n}\n\nexport function getAggregatedBalanceForAccount(\n state: AssetsControllerState,\n selectedInternalAccount: InternalAccount,\n enabledNetworkMap?: EnabledNetworkMap,\n accountTreeState?: AccountTreeControllerState,\n internalAccountsOrAccountIds?: InternalAccount[] | AccountId[],\n accountsById?: AccountsById,\n trace?: TraceCallback,\n): AggregatedBalanceForAccount {\n const startTime = trace ? performance.now() : 0;\n const { assetsBalance, assetsInfo, assetPreferences, assetsPrice } = state;\n\n const metadata = (assetsInfo ?? {}) as Record<Caip19AssetId, AssetMetadata>;\n\n const hasPrices =\n Boolean(assetsPrice) &&\n ((): boolean => {\n for (const key in assetsPrice) {\n if (Object.prototype.hasOwnProperty.call(assetsPrice, key)) {\n return true;\n }\n }\n return false;\n })();\n\n const accountsToAggregate = resolveAccountsToAggregate({\n selectedInternalAccount,\n accountTreeState,\n internalAccountsOrAccountIds,\n accountsById,\n });\n\n const assetInfoCache = makeAssetInfoCache();\n const merged = new Map<Caip19AssetId, AggRow>();\n\n for (const account of accountsToAggregate) {\n const accountId = account.id;\n const accountBalances =\n assetsBalance?.[accountId] ?? ({} as Record<Caip19AssetId, AssetBalance>);\n\n mergeBalancesIntoMap({\n out: merged,\n accountBalances,\n metadata,\n assetPreferences,\n enabledNetworkMap,\n assetInfoCache,\n });\n }\n\n // Materialize entries once\n const entries: AggregatedBalanceEntry[] = new Array(merged.size);\n let idx = 0;\n\n // If prices exist, compute totals in a single pass over merged.\n let totalBalanceInFiat = 0;\n let weightedNumerator = 0;\n\n for (const [assetId, row] of merged.entries()) {\n const { amount } = row;\n const entry: AggregatedBalanceEntry = {\n assetId,\n amount: amount.toFixed(),\n ...(row.decimals === undefined ? {} : { decimals: row.decimals }),\n ...(row.symbol === undefined ? {} : { symbol: row.symbol }),\n ...(row.name === undefined ? {} : { name: row.name }),\n };\n entries[idx] = entry;\n idx += 1;\n\n if (hasPrices) {\n const { price, pricePercentChange1d } = getPriceDatumFast(\n assetsPrice,\n assetId,\n );\n const contribution = amount.multipliedBy(price).toNumber();\n if (contribution > 0) {\n totalBalanceInFiat += contribution;\n weightedNumerator += contribution * pricePercentChange1d;\n }\n }\n }\n\n if (trace) {\n const durationMs = performance.now() - startTime;\n const uniqueNetworks = new Set<CaipChainId>();\n for (const assetId of merged.keys()) {\n const info = getAssetInfo(assetInfoCache, assetId);\n uniqueNetworks.add(info.chainId);\n }\n trace(\n {\n name: TRACE_AGGREGATED_BALANCE_SELECTOR,\n data: {\n duration_ms: durationMs,\n asset_count: merged.size,\n network_count: uniqueNetworks.size,\n account_count: accountsToAggregate.length,\n },\n tags: { controller: 'AssetsController' },\n },\n () => undefined,\n ).catch(() => {\n // Telemetry failure must not break.\n });\n }\n\n if (hasPrices) {\n const pricePercentChange1d =\n totalBalanceInFiat > 0 ? weightedNumerator / totalBalanceInFiat : 0;\n return {\n entries,\n totalBalanceInFiat,\n pricePercentChange1d,\n };\n }\n\n return { entries };\n}\n"]}
1
+ {"version":3,"file":"balance.cjs","sourceRoot":"","sources":["../../src/selectors/balance.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountTreeControllerState } from '@metamask/account-tree-controller';\nimport { toHex } from '@metamask/controller-utils';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { CaipChainId, Hex } from '@metamask/utils';\nimport {\n KnownCaipNamespace,\n isStrictHexString,\n parseCaipAssetType,\n parseCaipChainId,\n} from '@metamask/utils';\nimport BigNumberJS from 'bignumber.js';\n\nimport type { AssetsControllerState } from '../AssetsController';\nimport type {\n AccountId,\n AssetBalance,\n AssetMetadata,\n AssetPreferences,\n Caip19AssetId,\n} from '../types';\n\n// ============================================================================\n// TRACE NAMES — used in Sentry spans (search these strings in Discover)\n// ============================================================================\nconst TRACE_AGGREGATED_BALANCE_SELECTOR = 'AggregatedBalanceSelector';\n\nexport type EnabledNetworkMap =\n | Record<string, Record<string, boolean>>\n | undefined;\n\nexport type AggregatedBalanceEntry = {\n assetId: Caip19AssetId;\n amount: string;\n decimals?: number;\n symbol?: string;\n name?: string;\n};\n\nexport type AggregatedBalanceForAccount = {\n entries: AggregatedBalanceEntry[];\n totalBalanceInFiat?: number;\n pricePercentChange1d?: number;\n previousTotalInFiat?: number;\n};\n\ntype AccountLike = { id: AccountId };\nexport type AccountsById = Record<AccountId, InternalAccount>;\n\ntype PriceDatum = { price: number; pricePercentChange1d: number };\n\nconst ZERO_PRICE: PriceDatum = { price: 0, pricePercentChange1d: 0 };\n\nconst getAmountFromBalance = (balance: AssetBalance): string => {\n if (typeof balance === 'object' && balance !== null && 'amount' in balance) {\n const { amount } = balance as { amount?: unknown };\n return typeof amount === 'string' ? amount : '0';\n }\n return '0';\n};\n\nconst toBigNumberOrZero = (value: string): BigNumberJS => {\n const parsed = new BigNumberJS(value);\n return parsed.isNaN() || !parsed.isFinite() ? new BigNumberJS(0) : parsed;\n};\n\n/**\n * When state contains raw base units (e.g. SPORE \"16201541034.639288184\" with 9 decimals),\n * scale to human (16.2) before pricing. Only scale when amount >= 10^decimals so we don't\n * double-scale amounts that are already human (e.g. \"1\", \"0.227285\").\n *\n * @param amountRaw - Amount from state (may be raw or human).\n * @param decimals - Token decimals from metadata.\n * @returns Human amount for display and fiat (amountRaw or amountRaw / 10^decimals).\n */\nconst scaleToHumanIfRaw = (\n amountRaw: BigNumberJS,\n decimals: number,\n): BigNumberJS => {\n if (decimals <= 0) {\n return amountRaw;\n }\n const scale = new BigNumberJS(10).pow(decimals);\n if (amountRaw.lt(scale)) {\n return amountRaw;\n }\n return amountRaw.dividedBy(scale);\n};\n\nconst getPriceDatumFast = (\n assetsPrice: AssetsControllerState['assetsPrice'] | undefined,\n assetId: Caip19AssetId,\n): PriceDatum => {\n const raw = assetsPrice?.[assetId];\n if (!raw || typeof raw !== 'object') {\n return ZERO_PRICE;\n }\n const { price, pricePercentChange1d } = raw as {\n price?: unknown;\n pricePercentChange1d?: unknown;\n };\n return {\n price: typeof price === 'number' && Number.isFinite(price) ? price : 0,\n pricePercentChange1d:\n typeof pricePercentChange1d === 'number' &&\n Number.isFinite(pricePercentChange1d)\n ? pricePercentChange1d\n : 0,\n };\n};\n\n/**\n * Enablement lookup optimized:\n * - no array allocations\n * - early returns\n *\n * @param map - Enabled network map (namespace -> storageKey -> boolean)\n * @param id - Chain id as Hex or CAIP-2\n * @returns True if the chain is enabled or map is undefined\n */\nconst isChainEnabledByMap = (\n map: EnabledNetworkMap,\n id: Hex | CaipChainId,\n): boolean => {\n if (!map) {\n return true;\n }\n\n if (isStrictHexString(id)) {\n return Boolean(map[KnownCaipNamespace.Eip155]?.[id]);\n }\n\n const { namespace, reference } = parseCaipChainId(id);\n const namespaceMap = map[namespace];\n if (!namespaceMap) {\n return false;\n }\n\n // exact CAIP-2 id / reference\n if (namespaceMap[id] || namespaceMap[reference]) {\n return true;\n }\n\n // EVM: hex storage key\n if (namespace === KnownCaipNamespace.Eip155) {\n try {\n const storageKey = toHex(reference);\n return Boolean(namespaceMap[storageKey]);\n } catch {\n const parsedRef = Number.parseInt(reference, 10);\n if (Number.isFinite(parsedRef)) {\n return Boolean(namespaceMap[`0x${parsedRef.toString(16)}`]);\n }\n }\n }\n\n return false;\n};\n\n/**\n * Cache parsing results per assetId to avoid parseCaipAssetType/parseCaipChainId\n * being called multiple times across filtering + grouping + pricing.\n */\ntype AssetParseInfo = {\n chainId: CaipChainId;\n isEvm: boolean;\n};\n\nconst makeAssetInfoCache = (): Map<Caip19AssetId, AssetParseInfo> =>\n new Map<Caip19AssetId, AssetParseInfo>();\n\nconst getAssetInfo = (\n cache: Map<Caip19AssetId, AssetParseInfo>,\n assetId: Caip19AssetId,\n): AssetParseInfo => {\n const cached = cache.get(assetId);\n if (cached) {\n return cached;\n }\n const { chainId } = parseCaipAssetType(assetId);\n const { namespace } = parseCaipChainId(chainId);\n const info = { chainId, isEvm: namespace === KnownCaipNamespace.Eip155 };\n cache.set(assetId, info);\n return info;\n};\n\n/**\n * Merge across accounts without building per-account entries arrays.\n * Uses BigNumber for amount accumulation to avoid float precision loss.\n */\ntype AggRow = {\n amount: BigNumberJS;\n decimals?: number;\n symbol?: string;\n name?: string;\n};\n\nfunction mergeBalancesIntoMap(args: {\n out: Map<Caip19AssetId, AggRow>;\n accountBalances: Record<Caip19AssetId, AssetBalance>;\n metadata: Record<Caip19AssetId, AssetMetadata>;\n assetPreferences?: Record<Caip19AssetId, AssetPreferences>;\n enabledNetworkMap?: EnabledNetworkMap;\n assetInfoCache: Map<Caip19AssetId, AssetParseInfo>;\n}): void {\n const {\n out,\n accountBalances,\n metadata,\n assetPreferences,\n enabledNetworkMap,\n assetInfoCache,\n } = args;\n\n for (const assetId in accountBalances) {\n if (!Object.prototype.hasOwnProperty.call(accountBalances, assetId)) {\n continue;\n }\n const typedAssetId = assetId as Caip19AssetId;\n\n if (assetPreferences?.[typedAssetId]?.hidden) {\n continue;\n }\n\n const info = getAssetInfo(assetInfoCache, typedAssetId);\n if (!isChainEnabledByMap(enabledNetworkMap, info.chainId)) {\n continue;\n }\n\n const amountStr = getAmountFromBalance(accountBalances[typedAssetId]);\n let amountBn = toBigNumberOrZero(amountStr);\n const meta = metadata[typedAssetId];\n if (meta?.decimals !== undefined) {\n amountBn = scaleToHumanIfRaw(amountBn, meta.decimals);\n }\n if (amountBn.isZero()) {\n continue; // skip zeros early to reduce map pressure\n }\n\n const existing = out.get(typedAssetId);\n if (existing) {\n existing.amount = existing.amount.plus(amountBn);\n continue;\n }\n\n out.set(typedAssetId, {\n amount: amountBn,\n decimals: meta?.decimals,\n symbol: meta?.symbol,\n name: meta?.name,\n });\n }\n}\n\nexport function getGroupIdForAccount(\n accountTreeState: AccountTreeControllerState,\n accountId: AccountId,\n): string | undefined {\n const wallets = accountTreeState.accountTree?.wallets;\n if (!wallets) {\n return undefined;\n }\n for (const wallet of Object.values(wallets)) {\n for (const [groupId, group] of Object.entries(wallet?.groups ?? {})) {\n const accounts = group?.accounts;\n if (Array.isArray(accounts) && accounts.includes(accountId)) {\n return groupId;\n }\n }\n }\n return undefined;\n}\n\nexport function getInternalAccountsForGroup(\n accountTreeState: AccountTreeControllerState,\n accountsById: AccountsById,\n groupId: string,\n): InternalAccount[] {\n const wallets = accountTreeState.accountTree?.wallets;\n if (!wallets) {\n return [];\n }\n type GroupWithAccounts = { accounts?: AccountId[] };\n const getGroups = (\n walletItem: (typeof wallets)[keyof typeof wallets],\n ): Record<string, GroupWithAccounts> =>\n (walletItem?.groups ?? {}) as Record<string, GroupWithAccounts>;\n\n for (const wallet of Object.values(wallets)) {\n const group = getGroups(wallet)[groupId];\n if (!group?.accounts) {\n continue;\n }\n const result: InternalAccount[] = [];\n for (const id of group.accounts) {\n const acct = accountsById[id];\n if (acct) {\n result.push(acct);\n }\n }\n return result;\n }\n return [];\n}\n\nfunction getAccountIdsInSameGroup(\n accountTreeState: AccountTreeControllerState,\n selectedAccountId: AccountId,\n): AccountId[] | undefined {\n const groupId = getGroupIdForAccount(accountTreeState, selectedAccountId);\n if (!groupId) {\n return undefined;\n }\n const wallets = accountTreeState.accountTree?.wallets;\n if (!wallets) {\n return undefined;\n }\n type GroupWithAccounts = { accounts?: AccountId[] };\n const getGroups = (\n walletItem: (typeof wallets)[keyof typeof wallets],\n ): Record<string, GroupWithAccounts> =>\n (walletItem?.groups ?? {}) as Record<string, GroupWithAccounts>;\n\n for (const wallet of Object.values(wallets)) {\n const group = getGroups(wallet)[groupId];\n if (group?.accounts) {\n return [...group.accounts];\n }\n }\n return undefined;\n}\n\nfunction resolveAccountsToAggregate(args: {\n selectedInternalAccount: InternalAccount;\n accountTreeState?: AccountTreeControllerState;\n internalAccountsOrAccountIds?: InternalAccount[] | AccountId[];\n accountsById?: AccountsById;\n}): AccountLike[] {\n const {\n selectedInternalAccount,\n accountTreeState,\n internalAccountsOrAccountIds,\n accountsById,\n } = args;\n\n if (internalAccountsOrAccountIds && internalAccountsOrAccountIds.length > 0) {\n const first = internalAccountsOrAccountIds[0];\n if (typeof first === 'string') {\n const ids = internalAccountsOrAccountIds as AccountId[];\n const out: AccountLike[] = new Array(ids.length);\n for (let i = 0; i < ids.length; i++) {\n out[i] = { id: ids[i] };\n }\n return out;\n }\n return internalAccountsOrAccountIds as InternalAccount[];\n }\n\n if (\n accountTreeState &&\n accountsById &&\n Object.keys(accountsById).length > 0\n ) {\n const groupId = getGroupIdForAccount(\n accountTreeState,\n selectedInternalAccount.id,\n );\n if (groupId) {\n const groupAccounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsById,\n groupId,\n );\n if (groupAccounts.length > 0) {\n return groupAccounts;\n }\n }\n }\n\n if (accountTreeState) {\n const ids = getAccountIdsInSameGroup(\n accountTreeState,\n selectedInternalAccount.id,\n );\n if (ids && ids.length > 0) {\n const out: AccountLike[] = new Array(ids.length);\n for (let i = 0; i < ids.length; i++) {\n out[i] = { id: ids[i] };\n }\n return out;\n }\n }\n\n return [selectedInternalAccount];\n}\n\n/**\n * Get account ids that belong to a group, reading directly from the account\n * tree. Unlike {@link getInternalAccountsForGroup}, this does not require an\n * `accountsById` lookup map, which makes it convenient for balance aggregation\n * where only the ids are needed.\n *\n * @param accountTreeState - AccountTreeController state.\n * @param groupId - The account group id to look up.\n * @returns The list of account ids in the group, or an empty array.\n */\nexport function getAccountIdsForGroup(\n accountTreeState: AccountTreeControllerState,\n groupId: string,\n): AccountId[] {\n const wallets = accountTreeState.accountTree?.wallets ?? {};\n type GroupWithAccounts = { accounts?: AccountId[] };\n for (const wallet of Object.values(wallets)) {\n const groups = (wallet?.groups ?? {}) as Record<string, GroupWithAccounts>;\n const group = groups[groupId];\n if (group?.accounts) {\n return [...group.accounts];\n }\n }\n return [];\n}\n\n/**\n * Aggregate balances across an explicit list of accounts.\n *\n * This is the core aggregation engine shared by the account- and group-level\n * selectors. It intentionally takes a fully-resolved list of accounts so that\n * callers control account resolution and no \"selected account\" placeholder is\n * required.\n *\n * @param state - AssetsController state slice.\n * @param accounts - Accounts whose balances should be aggregated.\n * @param enabledNetworkMap - Optional map of enabled networks keyed by namespace.\n * @param trace - Optional trace callback for telemetry spans.\n * @returns Aggregated balance entries plus fiat totals when prices are present.\n */\nfunction aggregateBalances(\n state: AssetsControllerState,\n accounts: AccountLike[],\n enabledNetworkMap?: EnabledNetworkMap,\n trace?: TraceCallback,\n): AggregatedBalanceForAccount {\n const startTime = trace ? performance.now() : 0;\n const { assetsBalance, assetsInfo, assetPreferences, assetsPrice } = state;\n\n const metadata = (assetsInfo ?? {}) as Record<Caip19AssetId, AssetMetadata>;\n\n const hasPrices =\n Boolean(assetsPrice) &&\n ((): boolean => {\n for (const key in assetsPrice) {\n if (Object.prototype.hasOwnProperty.call(assetsPrice, key)) {\n return true;\n }\n }\n return false;\n })();\n\n const accountsToAggregate = accounts;\n\n const assetInfoCache = makeAssetInfoCache();\n const merged = new Map<Caip19AssetId, AggRow>();\n\n for (const account of accountsToAggregate) {\n const accountId = account.id;\n const accountBalances =\n assetsBalance?.[accountId] ?? ({} as Record<Caip19AssetId, AssetBalance>);\n\n mergeBalancesIntoMap({\n out: merged,\n accountBalances,\n metadata,\n assetPreferences,\n enabledNetworkMap,\n assetInfoCache,\n });\n }\n\n // Materialize entries once\n const entries: AggregatedBalanceEntry[] = new Array(merged.size);\n let idx = 0;\n\n // If prices exist, compute totals in a single pass over merged.\n let totalBalanceInFiat = 0;\n let previousTotalInFiat = 0;\n let weightedNumerator = 0;\n\n for (const [assetId, row] of merged.entries()) {\n const { amount } = row;\n const entry: AggregatedBalanceEntry = {\n assetId,\n amount: amount.toFixed(),\n ...(row.decimals === undefined ? {} : { decimals: row.decimals }),\n ...(row.symbol === undefined ? {} : { symbol: row.symbol }),\n ...(row.name === undefined ? {} : { name: row.name }),\n };\n entries[idx] = entry;\n idx += 1;\n\n if (hasPrices) {\n const { price, pricePercentChange1d } = getPriceDatumFast(\n assetsPrice,\n assetId,\n );\n const contribution = amount.multipliedBy(price).toNumber();\n if (contribution > 0) {\n totalBalanceInFiat += contribution;\n weightedNumerator += contribution * pricePercentChange1d;\n\n // A -100% move makes the denominator zero; treat it as flat so the\n // previous total never goes to infinity.\n const denom = Number((1 + pricePercentChange1d / 100).toFixed(8));\n previousTotalInFiat +=\n denom === 0 ? contribution : contribution / denom;\n }\n }\n }\n\n if (trace) {\n const durationMs = performance.now() - startTime;\n const uniqueNetworks = new Set<CaipChainId>();\n for (const assetId of merged.keys()) {\n const info = getAssetInfo(assetInfoCache, assetId);\n uniqueNetworks.add(info.chainId);\n }\n trace(\n {\n name: TRACE_AGGREGATED_BALANCE_SELECTOR,\n data: {\n duration_ms: durationMs,\n asset_count: merged.size,\n network_count: uniqueNetworks.size,\n account_count: accountsToAggregate.length,\n },\n tags: { controller: 'AssetsController' },\n },\n () => undefined,\n ).catch(() => {\n // Telemetry failure must not break.\n });\n }\n\n if (hasPrices) {\n const pricePercentChange1d =\n totalBalanceInFiat > 0 ? weightedNumerator / totalBalanceInFiat : 0;\n return {\n entries,\n totalBalanceInFiat,\n pricePercentChange1d,\n previousTotalInFiat,\n };\n }\n\n return { entries };\n}\n\n/**\n * Aggregate balances for an explicit list of account ids.\n *\n * Prefer this over {@link getAggregatedBalanceForAccount} when the set of\n * accounts to aggregate is already known (e.g. all accounts in a group), since\n * it does not require a \"selected account\" and therefore avoids the brittle\n * account-resolution heuristics.\n *\n * @param state - AssetsController state slice.\n * @param accountIds - Account ids whose balances should be aggregated.\n * @param enabledNetworkMap - Optional map of enabled networks keyed by namespace.\n * @param trace - Optional trace callback for telemetry spans.\n * @returns Aggregated balance entries plus fiat totals when prices are present.\n */\nexport function getAggregatedBalanceForAccountIds(\n state: AssetsControllerState,\n accountIds: AccountId[],\n enabledNetworkMap?: EnabledNetworkMap,\n trace?: TraceCallback,\n): AggregatedBalanceForAccount {\n const accounts: AccountLike[] = accountIds.map((id) => ({ id }));\n return aggregateBalances(state, accounts, enabledNetworkMap, trace);\n}\n\nexport function getAggregatedBalanceForAccount(\n state: AssetsControllerState,\n selectedInternalAccount: InternalAccount,\n enabledNetworkMap?: EnabledNetworkMap,\n accountTreeState?: AccountTreeControllerState,\n internalAccountsOrAccountIds?: InternalAccount[] | AccountId[],\n accountsById?: AccountsById,\n trace?: TraceCallback,\n): AggregatedBalanceForAccount {\n const accountsToAggregate = resolveAccountsToAggregate({\n selectedInternalAccount,\n accountTreeState,\n internalAccountsOrAccountIds,\n accountsById,\n });\n return aggregateBalances(\n state,\n accountsToAggregate,\n enabledNetworkMap,\n trace,\n );\n}\n\n// ============================================================================\n// WALLET- AND GROUP-LEVEL BALANCE CALCULATIONS\n// ============================================================================\n\n/**\n * Default user currency used when {@link AssetsControllerState.selectedCurrency}\n * is not set.\n */\nconst DEFAULT_USER_CURRENCY = 'usd';\n\nexport type AccountGroupBalance = {\n walletId: string;\n groupId: string;\n totalBalanceInUserCurrency: number;\n userCurrency: string;\n};\n\nexport type WalletBalance = {\n walletId: string;\n groups: Record<string, AccountGroupBalance>;\n totalBalanceInUserCurrency: number;\n userCurrency: string;\n};\n\nexport type AllWalletsBalance = {\n wallets: Record<string, WalletBalance>;\n totalBalanceInUserCurrency: number;\n userCurrency: string;\n};\n\nexport type BalanceChangePeriod = '1d' | '7d' | '30d';\n\nexport type BalanceChangeResult = {\n period: BalanceChangePeriod;\n currentTotalInUserCurrency: number;\n previousTotalInUserCurrency: number;\n amountChangeInUserCurrency: number;\n percentChange: number;\n userCurrency: string;\n};\n\n/**\n * Resolve the user currency for a balance calculation, falling back to a\n * sensible default when the controller has no selected currency.\n *\n * @param assetsControllerState - AssetsController state slice.\n * @returns The user currency code.\n */\nfunction getUserCurrency(assetsControllerState: AssetsControllerState): string {\n return assetsControllerState.selectedCurrency ?? DEFAULT_USER_CURRENCY;\n}\n\n/**\n * Resolve the current and previous totals for a change calculation.\n *\n * The AssetsController state only exposes a 1d price change, so non-`1d`\n * periods produce a zeroed change (previous equals current).\n *\n * @param totalBalanceInFiat - Aggregated current balance in user currency.\n * @param previousTotalInFiat - Aggregated prior balance summed per asset.\n * @param period - Period to compute the change for.\n * @returns The current and previous totals in user currency.\n */\nfunction getCurrentAndPrevious(\n totalBalanceInFiat: number,\n previousTotalInFiat: number,\n period: BalanceChangePeriod,\n): { current: number; previous: number } {\n const current = totalBalanceInFiat;\n const previous = period === '1d' ? previousTotalInFiat : current;\n return { current, previous };\n}\n\n/**\n * Build a {@link BalanceChangeResult} from current/previous totals.\n *\n * @param current - Current total in user currency.\n * @param previous - Previous total in user currency.\n * @param period - Period the change was computed for.\n * @param userCurrency - User currency code.\n * @returns The change result with delta and percent change.\n */\nfunction buildBalanceChangeResult(\n current: number,\n previous: number,\n period: BalanceChangePeriod,\n userCurrency: string,\n): BalanceChangeResult {\n const amountChange = current - previous;\n const percentChange = previous === 0 ? 0 : (amountChange / previous) * 100;\n return {\n period,\n currentTotalInUserCurrency: Number(current.toFixed(8)),\n previousTotalInUserCurrency: Number(previous.toFixed(8)),\n amountChangeInUserCurrency: Number(amountChange.toFixed(8)),\n percentChange: Number(percentChange.toFixed(8)),\n userCurrency,\n };\n}\n\n/**\n * Calculate aggregated balances for all wallets and groups.\n *\n * Mirrors the legacy `@metamask/assets-controllers` `calculateBalanceForAllWallets`\n * output shape, but sources every group total from the unified AssetsController\n * state via {@link getAggregatedBalanceForAccountIds}. The account tree is walked\n * to aggregate each group individually.\n *\n * @param assetsControllerState - AssetsController state slice.\n * @param accountTreeState - AccountTreeController state.\n * @param enabledNetworkMap - Map of enabled networks keyed by namespace.\n * @param trace - Optional trace callback forwarded to the aggregation selector.\n * @returns Aggregated balances for all wallets and groups.\n */\nexport function calculateBalanceForAllWallets(\n assetsControllerState: AssetsControllerState,\n accountTreeState: AccountTreeControllerState,\n enabledNetworkMap?: EnabledNetworkMap,\n trace?: TraceCallback,\n): AllWalletsBalance {\n const userCurrency = getUserCurrency(assetsControllerState);\n const wallets: AllWalletsBalance['wallets'] = {};\n let totalBalanceInUserCurrency = 0;\n\n type WalletWithGroups = { groups?: Record<string, unknown> };\n for (const [walletId, wallet] of Object.entries(\n accountTreeState.accountTree?.wallets ?? {},\n )) {\n const walletBalance: WalletBalance = {\n walletId,\n groups: {},\n totalBalanceInUserCurrency: 0,\n userCurrency,\n };\n\n const groups = (wallet as WalletWithGroups)?.groups ?? {};\n for (const groupId of Object.keys(groups)) {\n const accountIds = getAccountIdsForGroup(accountTreeState, groupId);\n const { totalBalanceInFiat = 0 } = getAggregatedBalanceForAccountIds(\n assetsControllerState,\n accountIds,\n enabledNetworkMap,\n trace,\n );\n\n walletBalance.groups[groupId] = {\n walletId,\n groupId,\n totalBalanceInUserCurrency: totalBalanceInFiat,\n userCurrency,\n };\n walletBalance.totalBalanceInUserCurrency += totalBalanceInFiat;\n }\n\n wallets[walletId] = walletBalance;\n totalBalanceInUserCurrency += walletBalance.totalBalanceInUserCurrency;\n }\n\n return { wallets, totalBalanceInUserCurrency, userCurrency };\n}\n\n/**\n * Calculate the portfolio value change for a single account group and period.\n *\n * @param assetsControllerState - AssetsController state slice.\n * @param accountTreeState - AccountTreeController state.\n * @param groupId - Account group id to compute the change for.\n * @param period - Change period (`1d` | `7d` | `30d`).\n * @param enabledNetworkMap - Map of enabled networks keyed by namespace.\n * @param trace - Optional trace callback forwarded to the aggregation selector.\n * @returns The change result for the requested period.\n */\nexport function calculateBalanceChangeForAccountGroup(\n assetsControllerState: AssetsControllerState,\n accountTreeState: AccountTreeControllerState,\n groupId: string,\n period: BalanceChangePeriod,\n enabledNetworkMap?: EnabledNetworkMap,\n trace?: TraceCallback,\n): BalanceChangeResult {\n const userCurrency = getUserCurrency(assetsControllerState);\n const accountIds = getAccountIdsForGroup(accountTreeState, groupId);\n const { totalBalanceInFiat = 0, previousTotalInFiat = totalBalanceInFiat } =\n getAggregatedBalanceForAccountIds(\n assetsControllerState,\n accountIds,\n enabledNetworkMap,\n trace,\n );\n\n const { current, previous } = getCurrentAndPrevious(\n totalBalanceInFiat,\n previousTotalInFiat,\n period,\n );\n\n return buildBalanceChangeResult(current, previous, period, userCurrency);\n}\n"]}
@@ -15,9 +15,89 @@ export type AggregatedBalanceForAccount = {
15
15
  entries: AggregatedBalanceEntry[];
16
16
  totalBalanceInFiat?: number;
17
17
  pricePercentChange1d?: number;
18
+ previousTotalInFiat?: number;
18
19
  };
19
20
  export type AccountsById = Record<AccountId, InternalAccount>;
20
21
  export declare function getGroupIdForAccount(accountTreeState: AccountTreeControllerState, accountId: AccountId): string | undefined;
21
22
  export declare function getInternalAccountsForGroup(accountTreeState: AccountTreeControllerState, accountsById: AccountsById, groupId: string): InternalAccount[];
23
+ /**
24
+ * Get account ids that belong to a group, reading directly from the account
25
+ * tree. Unlike {@link getInternalAccountsForGroup}, this does not require an
26
+ * `accountsById` lookup map, which makes it convenient for balance aggregation
27
+ * where only the ids are needed.
28
+ *
29
+ * @param accountTreeState - AccountTreeController state.
30
+ * @param groupId - The account group id to look up.
31
+ * @returns The list of account ids in the group, or an empty array.
32
+ */
33
+ export declare function getAccountIdsForGroup(accountTreeState: AccountTreeControllerState, groupId: string): AccountId[];
34
+ /**
35
+ * Aggregate balances for an explicit list of account ids.
36
+ *
37
+ * Prefer this over {@link getAggregatedBalanceForAccount} when the set of
38
+ * accounts to aggregate is already known (e.g. all accounts in a group), since
39
+ * it does not require a "selected account" and therefore avoids the brittle
40
+ * account-resolution heuristics.
41
+ *
42
+ * @param state - AssetsController state slice.
43
+ * @param accountIds - Account ids whose balances should be aggregated.
44
+ * @param enabledNetworkMap - Optional map of enabled networks keyed by namespace.
45
+ * @param trace - Optional trace callback for telemetry spans.
46
+ * @returns Aggregated balance entries plus fiat totals when prices are present.
47
+ */
48
+ export declare function getAggregatedBalanceForAccountIds(state: AssetsControllerState, accountIds: AccountId[], enabledNetworkMap?: EnabledNetworkMap, trace?: TraceCallback): AggregatedBalanceForAccount;
22
49
  export declare function getAggregatedBalanceForAccount(state: AssetsControllerState, selectedInternalAccount: InternalAccount, enabledNetworkMap?: EnabledNetworkMap, accountTreeState?: AccountTreeControllerState, internalAccountsOrAccountIds?: InternalAccount[] | AccountId[], accountsById?: AccountsById, trace?: TraceCallback): AggregatedBalanceForAccount;
50
+ export type AccountGroupBalance = {
51
+ walletId: string;
52
+ groupId: string;
53
+ totalBalanceInUserCurrency: number;
54
+ userCurrency: string;
55
+ };
56
+ export type WalletBalance = {
57
+ walletId: string;
58
+ groups: Record<string, AccountGroupBalance>;
59
+ totalBalanceInUserCurrency: number;
60
+ userCurrency: string;
61
+ };
62
+ export type AllWalletsBalance = {
63
+ wallets: Record<string, WalletBalance>;
64
+ totalBalanceInUserCurrency: number;
65
+ userCurrency: string;
66
+ };
67
+ export type BalanceChangePeriod = '1d' | '7d' | '30d';
68
+ export type BalanceChangeResult = {
69
+ period: BalanceChangePeriod;
70
+ currentTotalInUserCurrency: number;
71
+ previousTotalInUserCurrency: number;
72
+ amountChangeInUserCurrency: number;
73
+ percentChange: number;
74
+ userCurrency: string;
75
+ };
76
+ /**
77
+ * Calculate aggregated balances for all wallets and groups.
78
+ *
79
+ * Mirrors the legacy `@metamask/assets-controllers` `calculateBalanceForAllWallets`
80
+ * output shape, but sources every group total from the unified AssetsController
81
+ * state via {@link getAggregatedBalanceForAccountIds}. The account tree is walked
82
+ * to aggregate each group individually.
83
+ *
84
+ * @param assetsControllerState - AssetsController state slice.
85
+ * @param accountTreeState - AccountTreeController state.
86
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
87
+ * @param trace - Optional trace callback forwarded to the aggregation selector.
88
+ * @returns Aggregated balances for all wallets and groups.
89
+ */
90
+ export declare function calculateBalanceForAllWallets(assetsControllerState: AssetsControllerState, accountTreeState: AccountTreeControllerState, enabledNetworkMap?: EnabledNetworkMap, trace?: TraceCallback): AllWalletsBalance;
91
+ /**
92
+ * Calculate the portfolio value change for a single account group and period.
93
+ *
94
+ * @param assetsControllerState - AssetsController state slice.
95
+ * @param accountTreeState - AccountTreeController state.
96
+ * @param groupId - Account group id to compute the change for.
97
+ * @param period - Change period (`1d` | `7d` | `30d`).
98
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
99
+ * @param trace - Optional trace callback forwarded to the aggregation selector.
100
+ * @returns The change result for the requested period.
101
+ */
102
+ export declare function calculateBalanceChangeForAccountGroup(assetsControllerState: AssetsControllerState, accountTreeState: AccountTreeControllerState, groupId: string, period: BalanceChangePeriod, enabledNetworkMap?: EnabledNetworkMap, trace?: TraceCallback): BalanceChangeResult;
23
103
  //# sourceMappingURL=balance.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"balance.d.cts","sourceRoot":"","sources":["../../src/selectors/balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,0CAA0C;AAEpF,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAUtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,gCAA4B;AACjE,OAAO,KAAK,EACV,SAAS,EAIT,aAAa,EACd,qBAAiB;AAOlB,MAAM,MAAM,iBAAiB,GACzB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACvC,SAAS,CAAC;AAEd,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;AA+M9D,wBAAgB,oBAAoB,CAClC,gBAAgB,EAAE,0BAA0B,EAC5C,SAAS,EAAE,SAAS,GACnB,MAAM,GAAG,SAAS,CAcpB;AAED,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,0BAA0B,EAC5C,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,MAAM,GACd,eAAe,EAAE,CA0BnB;AA6FD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,qBAAqB,EAC5B,uBAAuB,EAAE,eAAe,EACxC,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,gBAAgB,CAAC,EAAE,0BAA0B,EAC7C,4BAA4B,CAAC,EAAE,eAAe,EAAE,GAAG,SAAS,EAAE,EAC9D,YAAY,CAAC,EAAE,YAAY,EAC3B,KAAK,CAAC,EAAE,aAAa,GACpB,2BAA2B,CA8G7B"}
1
+ {"version":3,"file":"balance.d.cts","sourceRoot":"","sources":["../../src/selectors/balance.ts"],"names":[],"mappings":"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"}
@@ -15,9 +15,89 @@ export type AggregatedBalanceForAccount = {
15
15
  entries: AggregatedBalanceEntry[];
16
16
  totalBalanceInFiat?: number;
17
17
  pricePercentChange1d?: number;
18
+ previousTotalInFiat?: number;
18
19
  };
19
20
  export type AccountsById = Record<AccountId, InternalAccount>;
20
21
  export declare function getGroupIdForAccount(accountTreeState: AccountTreeControllerState, accountId: AccountId): string | undefined;
21
22
  export declare function getInternalAccountsForGroup(accountTreeState: AccountTreeControllerState, accountsById: AccountsById, groupId: string): InternalAccount[];
23
+ /**
24
+ * Get account ids that belong to a group, reading directly from the account
25
+ * tree. Unlike {@link getInternalAccountsForGroup}, this does not require an
26
+ * `accountsById` lookup map, which makes it convenient for balance aggregation
27
+ * where only the ids are needed.
28
+ *
29
+ * @param accountTreeState - AccountTreeController state.
30
+ * @param groupId - The account group id to look up.
31
+ * @returns The list of account ids in the group, or an empty array.
32
+ */
33
+ export declare function getAccountIdsForGroup(accountTreeState: AccountTreeControllerState, groupId: string): AccountId[];
34
+ /**
35
+ * Aggregate balances for an explicit list of account ids.
36
+ *
37
+ * Prefer this over {@link getAggregatedBalanceForAccount} when the set of
38
+ * accounts to aggregate is already known (e.g. all accounts in a group), since
39
+ * it does not require a "selected account" and therefore avoids the brittle
40
+ * account-resolution heuristics.
41
+ *
42
+ * @param state - AssetsController state slice.
43
+ * @param accountIds - Account ids whose balances should be aggregated.
44
+ * @param enabledNetworkMap - Optional map of enabled networks keyed by namespace.
45
+ * @param trace - Optional trace callback for telemetry spans.
46
+ * @returns Aggregated balance entries plus fiat totals when prices are present.
47
+ */
48
+ export declare function getAggregatedBalanceForAccountIds(state: AssetsControllerState, accountIds: AccountId[], enabledNetworkMap?: EnabledNetworkMap, trace?: TraceCallback): AggregatedBalanceForAccount;
22
49
  export declare function getAggregatedBalanceForAccount(state: AssetsControllerState, selectedInternalAccount: InternalAccount, enabledNetworkMap?: EnabledNetworkMap, accountTreeState?: AccountTreeControllerState, internalAccountsOrAccountIds?: InternalAccount[] | AccountId[], accountsById?: AccountsById, trace?: TraceCallback): AggregatedBalanceForAccount;
50
+ export type AccountGroupBalance = {
51
+ walletId: string;
52
+ groupId: string;
53
+ totalBalanceInUserCurrency: number;
54
+ userCurrency: string;
55
+ };
56
+ export type WalletBalance = {
57
+ walletId: string;
58
+ groups: Record<string, AccountGroupBalance>;
59
+ totalBalanceInUserCurrency: number;
60
+ userCurrency: string;
61
+ };
62
+ export type AllWalletsBalance = {
63
+ wallets: Record<string, WalletBalance>;
64
+ totalBalanceInUserCurrency: number;
65
+ userCurrency: string;
66
+ };
67
+ export type BalanceChangePeriod = '1d' | '7d' | '30d';
68
+ export type BalanceChangeResult = {
69
+ period: BalanceChangePeriod;
70
+ currentTotalInUserCurrency: number;
71
+ previousTotalInUserCurrency: number;
72
+ amountChangeInUserCurrency: number;
73
+ percentChange: number;
74
+ userCurrency: string;
75
+ };
76
+ /**
77
+ * Calculate aggregated balances for all wallets and groups.
78
+ *
79
+ * Mirrors the legacy `@metamask/assets-controllers` `calculateBalanceForAllWallets`
80
+ * output shape, but sources every group total from the unified AssetsController
81
+ * state via {@link getAggregatedBalanceForAccountIds}. The account tree is walked
82
+ * to aggregate each group individually.
83
+ *
84
+ * @param assetsControllerState - AssetsController state slice.
85
+ * @param accountTreeState - AccountTreeController state.
86
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
87
+ * @param trace - Optional trace callback forwarded to the aggregation selector.
88
+ * @returns Aggregated balances for all wallets and groups.
89
+ */
90
+ export declare function calculateBalanceForAllWallets(assetsControllerState: AssetsControllerState, accountTreeState: AccountTreeControllerState, enabledNetworkMap?: EnabledNetworkMap, trace?: TraceCallback): AllWalletsBalance;
91
+ /**
92
+ * Calculate the portfolio value change for a single account group and period.
93
+ *
94
+ * @param assetsControllerState - AssetsController state slice.
95
+ * @param accountTreeState - AccountTreeController state.
96
+ * @param groupId - Account group id to compute the change for.
97
+ * @param period - Change period (`1d` | `7d` | `30d`).
98
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
99
+ * @param trace - Optional trace callback forwarded to the aggregation selector.
100
+ * @returns The change result for the requested period.
101
+ */
102
+ export declare function calculateBalanceChangeForAccountGroup(assetsControllerState: AssetsControllerState, accountTreeState: AccountTreeControllerState, groupId: string, period: BalanceChangePeriod, enabledNetworkMap?: EnabledNetworkMap, trace?: TraceCallback): BalanceChangeResult;
23
103
  //# sourceMappingURL=balance.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"balance.d.mts","sourceRoot":"","sources":["../../src/selectors/balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,0CAA0C;AAEpF,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAUtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,gCAA4B;AACjE,OAAO,KAAK,EACV,SAAS,EAIT,aAAa,EACd,qBAAiB;AAOlB,MAAM,MAAM,iBAAiB,GACzB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACvC,SAAS,CAAC;AAEd,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;AA+M9D,wBAAgB,oBAAoB,CAClC,gBAAgB,EAAE,0BAA0B,EAC5C,SAAS,EAAE,SAAS,GACnB,MAAM,GAAG,SAAS,CAcpB;AAED,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,0BAA0B,EAC5C,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,MAAM,GACd,eAAe,EAAE,CA0BnB;AA6FD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,qBAAqB,EAC5B,uBAAuB,EAAE,eAAe,EACxC,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,gBAAgB,CAAC,EAAE,0BAA0B,EAC7C,4BAA4B,CAAC,EAAE,eAAe,EAAE,GAAG,SAAS,EAAE,EAC9D,YAAY,CAAC,EAAE,YAAY,EAC3B,KAAK,CAAC,EAAE,aAAa,GACpB,2BAA2B,CA8G7B"}
1
+ {"version":3,"file":"balance.d.mts","sourceRoot":"","sources":["../../src/selectors/balance.ts"],"names":[],"mappings":"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"}