@metamask/assets-controllers 73.1.0 → 73.3.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 (96) hide show
  1. package/CHANGELOG.md +43 -1
  2. package/dist/AccountTrackerController.cjs +51 -1
  3. package/dist/AccountTrackerController.cjs.map +1 -1
  4. package/dist/AccountTrackerController.d.cts +40 -1
  5. package/dist/AccountTrackerController.d.cts.map +1 -1
  6. package/dist/AccountTrackerController.d.mts +40 -1
  7. package/dist/AccountTrackerController.d.mts.map +1 -1
  8. package/dist/AccountTrackerController.mjs +51 -1
  9. package/dist/AccountTrackerController.mjs.map +1 -1
  10. package/dist/TokenBalancesController.cjs +278 -319
  11. package/dist/TokenBalancesController.cjs.map +1 -1
  12. package/dist/TokenBalancesController.d.cts +51 -93
  13. package/dist/TokenBalancesController.d.cts.map +1 -1
  14. package/dist/TokenBalancesController.d.mts +51 -93
  15. package/dist/TokenBalancesController.d.mts.map +1 -1
  16. package/dist/TokenBalancesController.mjs +277 -317
  17. package/dist/TokenBalancesController.mjs.map +1 -1
  18. package/dist/assetsUtil.cjs +13 -1
  19. package/dist/assetsUtil.cjs.map +1 -1
  20. package/dist/assetsUtil.d.cts +8 -0
  21. package/dist/assetsUtil.d.cts.map +1 -1
  22. package/dist/assetsUtil.d.mts +8 -0
  23. package/dist/assetsUtil.d.mts.map +1 -1
  24. package/dist/assetsUtil.mjs +12 -1
  25. package/dist/assetsUtil.mjs.map +1 -1
  26. package/dist/balances.cjs +447 -0
  27. package/dist/balances.cjs.map +1 -0
  28. package/dist/balances.d.cts +88 -0
  29. package/dist/balances.d.cts.map +1 -0
  30. package/dist/balances.d.mts +88 -0
  31. package/dist/balances.d.mts.map +1 -0
  32. package/dist/balances.mjs +441 -0
  33. package/dist/balances.mjs.map +1 -0
  34. package/dist/constants.cjs +13 -1
  35. package/dist/constants.cjs.map +1 -1
  36. package/dist/constants.d.cts +1 -0
  37. package/dist/constants.d.cts.map +1 -1
  38. package/dist/constants.d.mts +1 -0
  39. package/dist/constants.d.mts.map +1 -1
  40. package/dist/constants.mjs +12 -0
  41. package/dist/constants.mjs.map +1 -1
  42. package/dist/index.cjs +6 -3
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +6 -4
  45. package/dist/index.d.cts.map +1 -1
  46. package/dist/index.d.mts +6 -4
  47. package/dist/index.d.mts.map +1 -1
  48. package/dist/index.mjs +2 -1
  49. package/dist/index.mjs.map +1 -1
  50. package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs +286 -0
  51. package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs.map +1 -0
  52. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts +30 -0
  53. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts.map +1 -0
  54. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts +30 -0
  55. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts.map +1 -0
  56. package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs +286 -0
  57. package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs.map +1 -0
  58. package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs +35 -1
  59. package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs.map +1 -1
  60. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts +16 -0
  61. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts.map +1 -1
  62. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts +16 -0
  63. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts.map +1 -1
  64. package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs +33 -0
  65. package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs.map +1 -1
  66. package/dist/multi-chain-accounts-service/types.cjs.map +1 -1
  67. package/dist/multi-chain-accounts-service/types.d.cts +8 -0
  68. package/dist/multi-chain-accounts-service/types.d.cts.map +1 -1
  69. package/dist/multi-chain-accounts-service/types.d.mts +8 -0
  70. package/dist/multi-chain-accounts-service/types.d.mts.map +1 -1
  71. package/dist/multi-chain-accounts-service/types.mjs.map +1 -1
  72. package/dist/multicall.cjs +457 -1
  73. package/dist/multicall.cjs.map +1 -1
  74. package/dist/multicall.d.cts +51 -0
  75. package/dist/multicall.d.cts.map +1 -1
  76. package/dist/multicall.d.mts +51 -0
  77. package/dist/multicall.d.mts.map +1 -1
  78. package/dist/multicall.mjs +457 -0
  79. package/dist/multicall.mjs.map +1 -1
  80. package/dist/rpc-service/rpc-balance-fetcher.cjs +184 -0
  81. package/dist/rpc-service/rpc-balance-fetcher.cjs.map +1 -0
  82. package/dist/rpc-service/rpc-balance-fetcher.d.cts +34 -0
  83. package/dist/rpc-service/rpc-balance-fetcher.d.cts.map +1 -0
  84. package/dist/rpc-service/rpc-balance-fetcher.d.mts +34 -0
  85. package/dist/rpc-service/rpc-balance-fetcher.d.mts.map +1 -0
  86. package/dist/rpc-service/rpc-balance-fetcher.mjs +184 -0
  87. package/dist/rpc-service/rpc-balance-fetcher.mjs.map +1 -0
  88. package/package.json +11 -11
  89. package/dist/selectors/balanceSelectors.cjs +0 -328
  90. package/dist/selectors/balanceSelectors.cjs.map +0 -1
  91. package/dist/selectors/balanceSelectors.d.cts +0 -1676
  92. package/dist/selectors/balanceSelectors.d.cts.map +0 -1
  93. package/dist/selectors/balanceSelectors.d.mts +0 -1676
  94. package/dist/selectors/balanceSelectors.d.mts.map +0 -1
  95. package/dist/selectors/balanceSelectors.mjs +0 -321
  96. package/dist/selectors/balanceSelectors.mjs.map +0 -1
@@ -0,0 +1,88 @@
1
+ import type { AccountTreeControllerState } from "@metamask/account-tree-controller";
2
+ import type { AccountsControllerState } from "@metamask/accounts-controller";
3
+ import type { CurrencyRateState } from "./CurrencyRateController.mjs";
4
+ import type { MultichainAssetsRatesControllerState } from "./MultichainAssetsRatesController/index.mjs";
5
+ import type { MultichainBalancesControllerState } from "./MultichainBalancesController/index.mjs";
6
+ import type { TokenBalancesControllerState } from "./TokenBalancesController.mjs";
7
+ import type { TokenRatesControllerState } from "./TokenRatesController.mjs";
8
+ import type { TokensControllerState } from "./TokensController.mjs";
9
+ export type AccountGroupBalance = {
10
+ walletId: string;
11
+ groupId: string;
12
+ totalBalanceInUserCurrency: number;
13
+ userCurrency: string;
14
+ };
15
+ export type WalletBalance = {
16
+ walletId: string;
17
+ groups: Record<string, AccountGroupBalance>;
18
+ totalBalanceInUserCurrency: number;
19
+ userCurrency: string;
20
+ };
21
+ export type AllWalletsBalance = {
22
+ wallets: Record<string, WalletBalance>;
23
+ totalBalanceInUserCurrency: number;
24
+ userCurrency: string;
25
+ };
26
+ export type BalanceChangePeriod = '1d' | '7d' | '30d';
27
+ export type BalanceChangeResult = {
28
+ period: BalanceChangePeriod;
29
+ currentTotalInUserCurrency: number;
30
+ previousTotalInUserCurrency: number;
31
+ amountChangeInUserCurrency: number;
32
+ percentChange: number;
33
+ userCurrency: string;
34
+ };
35
+ /**
36
+ * Calculate balances for all wallets and groups.
37
+ * Pure function – accepts controller states and returns aggregated totals.
38
+ *
39
+ * @param accountTreeState - AccountTreeController state
40
+ * @param accountsState - AccountsController state
41
+ * @param tokenBalancesState - TokenBalancesController state
42
+ * @param tokenRatesState - TokenRatesController state
43
+ * @param multichainRatesState - MultichainAssetsRatesController state
44
+ * @param multichainBalancesState - MultichainBalancesController state
45
+ * @param tokensState - TokensController state
46
+ * @param currencyRateState - CurrencyRateController state
47
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace
48
+ * @returns Aggregated balances for all wallets
49
+ */
50
+ export declare function calculateBalanceForAllWallets(accountTreeState: AccountTreeControllerState, accountsState: AccountsControllerState, tokenBalancesState: TokenBalancesControllerState, tokenRatesState: TokenRatesControllerState, multichainRatesState: MultichainAssetsRatesControllerState, multichainBalancesState: MultichainBalancesControllerState, tokensState: TokensControllerState, currencyRateState: CurrencyRateState, enabledNetworkMap: Record<string, Record<string, boolean>> | undefined): AllWalletsBalance;
51
+ /**
52
+ * Calculate aggregated portfolio value change for a given period (1d, 7d, 30d).
53
+ * Logic mirrors extension/mobile historical aggregation:
54
+ * - For each asset with available percent change for the requested period, compute current value in user currency.
55
+ * - Reconstruct previous value by dividing current by (1 + percent/100).
56
+ * - Sum across all assets, then compute amount change and percent change.
57
+ *
58
+ * @param accountTreeState - AccountTreeController state.
59
+ * @param accountsState - AccountsController state.
60
+ * @param tokenBalancesState - TokenBalancesController state.
61
+ * @param tokenRatesState - TokenRatesController state.
62
+ * @param multichainRatesState - MultichainAssetsRatesController state.
63
+ * @param multichainBalancesState - MultichainBalancesController state.
64
+ * @param tokensState - TokensController state.
65
+ * @param currencyRateState - CurrencyRateController state.
66
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
67
+ * @param period - Period to compute change for ('1d' | '7d' | '30d').
68
+ * @returns Aggregated change details for the requested period.
69
+ */
70
+ export declare function calculateBalanceChangeForAllWallets(accountTreeState: AccountTreeControllerState, accountsState: AccountsControllerState, tokenBalancesState: TokenBalancesControllerState, tokenRatesState: TokenRatesControllerState, multichainRatesState: MultichainAssetsRatesControllerState, multichainBalancesState: MultichainBalancesControllerState, tokensState: TokensControllerState, currencyRateState: CurrencyRateState, enabledNetworkMap: Record<string, Record<string, boolean>> | undefined, period: BalanceChangePeriod): BalanceChangeResult;
71
+ /**
72
+ * Calculate portfolio value change for a specific account group and period.
73
+ *
74
+ * @param accountTreeState - AccountTreeController state.
75
+ * @param accountsState - AccountsController state.
76
+ * @param tokenBalancesState - TokenBalancesController state.
77
+ * @param tokenRatesState - TokenRatesController state.
78
+ * @param multichainRatesState - MultichainAssetsRatesController state.
79
+ * @param multichainBalancesState - MultichainBalancesController state.
80
+ * @param tokensState - TokensController state.
81
+ * @param currencyRateState - CurrencyRateController state.
82
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
83
+ * @param groupId - Account group ID to compute change for.
84
+ * @param period - Change period ('1d' | '7d' | '30d').
85
+ * @returns Change result including current, previous, delta, percent, and period.
86
+ */
87
+ export declare function calculateBalanceChangeForAccountGroup(accountTreeState: AccountTreeControllerState, accountsState: AccountsControllerState, tokenBalancesState: TokenBalancesControllerState, tokenRatesState: TokenRatesControllerState, multichainRatesState: MultichainAssetsRatesControllerState, multichainBalancesState: MultichainBalancesControllerState, tokensState: TokensControllerState, currencyRateState: CurrencyRateState, enabledNetworkMap: Record<string, Record<string, boolean>> | undefined, groupId: string, period: BalanceChangePeriod): BalanceChangeResult;
88
+ //# sourceMappingURL=balances.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balances.d.mts","sourceRoot":"","sources":["../src/balances.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,441 @@
1
+ import { isEvmAccountType } from "@metamask/keyring-api";
2
+ import { KnownCaipNamespace, parseCaipAssetType, parseCaipChainId, isStrictHexString } from "@metamask/utils";
3
+ const evmRatePropertiesRecord = {
4
+ '1d': 'pricePercentChange1d',
5
+ '7d': 'pricePercentChange7d',
6
+ '30d': 'pricePercentChange30d',
7
+ };
8
+ const nonEvmRatePropertiesRecord = {
9
+ '1d': 'P1D',
10
+ '7d': 'P7D',
11
+ '30d': 'P30D',
12
+ };
13
+ const isChainEnabledByMap = (map, id) => {
14
+ if (!map) {
15
+ return true;
16
+ }
17
+ if (isStrictHexString(id)) {
18
+ return Boolean(map[KnownCaipNamespace.Eip155]?.[id]);
19
+ }
20
+ const { namespace } = parseCaipChainId(id);
21
+ return Boolean(map[namespace]?.[id]);
22
+ };
23
+ const getWalletIdFromGroupId = (groupId) => {
24
+ return groupId.split('/')[0];
25
+ };
26
+ const getInternalAccountsForGroup = (accountTreeState, accountsState, groupId) => {
27
+ const walletId = getWalletIdFromGroupId(groupId);
28
+ const wallet = accountTreeState.accountTree.wallets[walletId];
29
+ if (!wallet) {
30
+ return [];
31
+ }
32
+ const group = wallet.groups[groupId];
33
+ if (!group) {
34
+ return [];
35
+ }
36
+ return group.accounts
37
+ .map((accountId) => accountsState.internalAccounts.accounts[accountId])
38
+ .filter(Boolean);
39
+ };
40
+ const isNonNaNNumber = (value) => typeof value === 'number' && !Number.isNaN(value);
41
+ /**
42
+ * Combined function that gets valid token balances with calculation data
43
+ *
44
+ * @param account - Internal account.
45
+ * @param tokenBalancesState - Token balances state.
46
+ * @param tokensState - Tokens state.
47
+ * @param tokenRatesState - Token rates state.
48
+ * @param currencyRateState - Currency rate state.
49
+ * @param isEvmChainEnabled - Predicate to check EVM chain enablement.
50
+ * @returns token calculation data
51
+ */
52
+ function getEvmTokenBalances(account, tokenBalancesState, tokensState, tokenRatesState, currencyRateState, isEvmChainEnabled) {
53
+ const accountBalances = tokenBalancesState.tokenBalances[account.address] ?? {};
54
+ return Object.entries(accountBalances)
55
+ .filter(([chainId]) => isEvmChainEnabled(chainId))
56
+ .flatMap(([chainId, chainBalances]) => Object.entries(chainBalances).map(([tokenAddress, balance]) => ({
57
+ chainId: chainId,
58
+ tokenAddress: tokenAddress,
59
+ balance,
60
+ })))
61
+ .map((tokenBalance) => {
62
+ const { chainId, tokenAddress, balance } = tokenBalance;
63
+ // Get Token Info
64
+ const accountTokens = tokensState?.allTokens?.[chainId]?.[account.address];
65
+ const token = accountTokens?.find((t) => t.address === tokenAddress);
66
+ if (!token) {
67
+ return null;
68
+ }
69
+ // Get market data
70
+ const tokenMarketData = tokenRatesState?.marketData?.[chainId]?.[tokenAddress];
71
+ if (!tokenMarketData?.price) {
72
+ return null;
73
+ }
74
+ // Get conversion rate
75
+ const nativeToUserRate = currencyRateState.currencyRates[tokenMarketData.currency]
76
+ ?.conversionRate;
77
+ if (!nativeToUserRate) {
78
+ return null;
79
+ }
80
+ // Calculate values
81
+ const decimals = isNonNaNNumber(token.decimals) ? token.decimals : 18;
82
+ const decimalBalance = parseInt(balance, 16);
83
+ if (!isNonNaNNumber(decimalBalance)) {
84
+ return null;
85
+ }
86
+ const userCurrencyValue = (decimalBalance / Math.pow(10, decimals)) *
87
+ tokenMarketData.price *
88
+ nativeToUserRate;
89
+ return {
90
+ userCurrencyValue,
91
+ tokenMarketData, // Only needed for change calculations
92
+ };
93
+ })
94
+ .filter((item) => item !== null);
95
+ }
96
+ /**
97
+ * Combined function that gets valid non-EVM asset balances with calculation data
98
+ *
99
+ * @param account - Internal account.
100
+ * @param multichainBalancesState - Multichain balances state.
101
+ * @param multichainRatesState - Multichain rates state.
102
+ * @param isAssetChainEnabled - Predicate to check asset chain enablement.
103
+ * @returns token calculation data
104
+ */
105
+ function getNonEvmAssetBalances(account, multichainBalancesState, multichainRatesState, isAssetChainEnabled) {
106
+ const accountBalances = multichainBalancesState.balances[account.id] ?? {};
107
+ return Object.entries(accountBalances)
108
+ .filter(([assetId]) => isAssetChainEnabled(assetId))
109
+ .map(([assetId, balanceData]) => {
110
+ const balanceAmount = parseFloat(balanceData.amount);
111
+ if (Number.isNaN(balanceAmount)) {
112
+ return null;
113
+ }
114
+ const conversionRate = multichainRatesState.conversionRates[assetId];
115
+ if (!conversionRate) {
116
+ return null;
117
+ }
118
+ const conversionRateValue = parseFloat(conversionRate.rate);
119
+ if (Number.isNaN(conversionRateValue)) {
120
+ return null;
121
+ }
122
+ const userCurrencyValue = balanceAmount * conversionRateValue;
123
+ return {
124
+ assetId: assetId,
125
+ userCurrencyValue,
126
+ conversionRate, // Only needed for change calculations
127
+ };
128
+ })
129
+ .filter((item) => item !== null);
130
+ }
131
+ /**
132
+ * Sum EVM account token balances in user currency.
133
+ *
134
+ * @param account - Internal account.
135
+ * @param tokenBalancesState - Token balances state.
136
+ * @param tokensState - Tokens state.
137
+ * @param tokenRatesState - Token rates state.
138
+ * @param currencyRateState - Currency rate state.
139
+ * @param isEvmChainEnabled - Predicate to check EVM chain enablement.
140
+ * @returns Total value in user currency.
141
+ */
142
+ function sumEvmAccountBalanceInUserCurrency(account, tokenBalancesState, tokensState, tokenRatesState, currencyRateState, isEvmChainEnabled) {
143
+ const tokenBalances = getEvmTokenBalances(account, tokenBalancesState, tokensState, tokenRatesState, currencyRateState, isEvmChainEnabled);
144
+ return tokenBalances.reduce((a, b) => a + b.userCurrencyValue, 0);
145
+ }
146
+ /**
147
+ * Sum non‑EVM account balances in user currency from multichain sources.
148
+ *
149
+ * @param account - Internal account.
150
+ * @param multichainBalancesState - Multichain balances state.
151
+ * @param multichainRatesState - Multichain rates state.
152
+ * @param isAssetChainEnabled - Predicate to check asset chain enablement.
153
+ * @returns Total value in user currency.
154
+ */
155
+ function sumNonEvmAccountBalanceInUserCurrency(account, multichainBalancesState, multichainRatesState, isAssetChainEnabled) {
156
+ const assetBalances = getNonEvmAssetBalances(account, multichainBalancesState, multichainRatesState, isAssetChainEnabled);
157
+ return assetBalances.reduce((a, b) => a + b.userCurrencyValue, 0);
158
+ }
159
+ /**
160
+ * Calculate balances for all wallets and groups.
161
+ * Pure function – accepts controller states and returns aggregated totals.
162
+ *
163
+ * @param accountTreeState - AccountTreeController state
164
+ * @param accountsState - AccountsController state
165
+ * @param tokenBalancesState - TokenBalancesController state
166
+ * @param tokenRatesState - TokenRatesController state
167
+ * @param multichainRatesState - MultichainAssetsRatesController state
168
+ * @param multichainBalancesState - MultichainBalancesController state
169
+ * @param tokensState - TokensController state
170
+ * @param currencyRateState - CurrencyRateController state
171
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace
172
+ * @returns Aggregated balances for all wallets
173
+ */
174
+ export function calculateBalanceForAllWallets(accountTreeState, accountsState, tokenBalancesState, tokenRatesState, multichainRatesState, multichainBalancesState, tokensState, currencyRateState, enabledNetworkMap) {
175
+ const isEvmChainEnabled = (chainId) => isChainEnabledByMap(enabledNetworkMap, chainId);
176
+ const isAssetChainEnabled = (assetId) => isChainEnabledByMap(enabledNetworkMap, parseCaipAssetType(assetId).chainId);
177
+ const getBalance = {
178
+ evm: (account) => sumEvmAccountBalanceInUserCurrency(account, tokenBalancesState, tokensState, tokenRatesState, currencyRateState, isEvmChainEnabled),
179
+ nonEvm: (account) => sumNonEvmAccountBalanceInUserCurrency(account, multichainBalancesState, multichainRatesState, isAssetChainEnabled),
180
+ };
181
+ const getFlatAccountBalances = () => Object.entries(accountTreeState.accountTree.wallets ?? {})
182
+ .flatMap(([walletId, wallet]) => Object.keys(wallet?.groups || {}).flatMap((groupId) => {
183
+ const accounts = getInternalAccountsForGroup(accountTreeState, accountsState, groupId);
184
+ return accounts.map((account) => ({
185
+ walletId,
186
+ groupId,
187
+ account,
188
+ isEvm: isEvmAccountType(account.type),
189
+ }));
190
+ }))
191
+ .map((flatAccount) => {
192
+ const flatAccountWithBalance = flatAccount;
193
+ flatAccountWithBalance.balance = flatAccount.isEvm
194
+ ? getBalance.evm(flatAccount.account)
195
+ : getBalance.nonEvm(flatAccount.account);
196
+ return flatAccountWithBalance;
197
+ });
198
+ const getAggWalletBalance = (flatAccountBalances) => flatAccountBalances.reduce((a, b) => a + b.balance, 0);
199
+ const getWalletBalances = (flatAccountBalances) => {
200
+ const wallets = {};
201
+ const defaultWalletBalance = (walletId) => ({
202
+ walletId,
203
+ groups: {},
204
+ totalBalanceInUserCurrency: 0,
205
+ userCurrency: currencyRateState.currentCurrency,
206
+ });
207
+ const defaultGroupBalance = (walletId, groupId) => ({
208
+ walletId,
209
+ groupId,
210
+ totalBalanceInUserCurrency: 0,
211
+ userCurrency: currencyRateState.currentCurrency,
212
+ });
213
+ flatAccountBalances.forEach((flatAccount) => {
214
+ var _a;
215
+ const { walletId, groupId, balance } = flatAccount;
216
+ wallets[walletId] ?? (wallets[walletId] = defaultWalletBalance(walletId));
217
+ (_a = wallets[walletId].groups)[groupId] ?? (_a[groupId] = defaultGroupBalance(walletId, groupId));
218
+ wallets[walletId].groups[groupId].totalBalanceInUserCurrency += balance;
219
+ wallets[walletId].totalBalanceInUserCurrency += balance;
220
+ });
221
+ // Ensure all groups (including empty ones) are represented
222
+ Object.entries(accountTreeState.accountTree.wallets ?? {}).forEach(([walletId, wallet]) => {
223
+ if (!wallet) {
224
+ return;
225
+ }
226
+ wallets[walletId] ?? (wallets[walletId] = defaultWalletBalance(walletId));
227
+ Object.keys(wallet.groups || {}).forEach((groupId) => {
228
+ var _a;
229
+ (_a = wallets[walletId].groups)[groupId] ?? (_a[groupId] = defaultGroupBalance(walletId, groupId));
230
+ });
231
+ });
232
+ return wallets;
233
+ };
234
+ const flatAccounts = getFlatAccountBalances();
235
+ return {
236
+ wallets: getWalletBalances(flatAccounts),
237
+ totalBalanceInUserCurrency: getAggWalletBalance(flatAccounts),
238
+ userCurrency: currencyRateState.currentCurrency,
239
+ };
240
+ }
241
+ /**
242
+ * Calculate aggregated portfolio value change for a given period (1d, 7d, 30d).
243
+ * Logic mirrors extension/mobile historical aggregation:
244
+ * - For each asset with available percent change for the requested period, compute current value in user currency.
245
+ * - Reconstruct previous value by dividing current by (1 + percent/100).
246
+ * - Sum across all assets, then compute amount change and percent change.
247
+ *
248
+ * @param accountTreeState - AccountTreeController state.
249
+ * @param accountsState - AccountsController state.
250
+ * @param tokenBalancesState - TokenBalancesController state.
251
+ * @param tokenRatesState - TokenRatesController state.
252
+ * @param multichainRatesState - MultichainAssetsRatesController state.
253
+ * @param multichainBalancesState - MultichainBalancesController state.
254
+ * @param tokensState - TokensController state.
255
+ * @param currencyRateState - CurrencyRateController state.
256
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
257
+ * @param period - Period to compute change for ('1d' | '7d' | '30d').
258
+ * @returns Aggregated change details for the requested period.
259
+ */
260
+ export function calculateBalanceChangeForAllWallets(accountTreeState, accountsState, tokenBalancesState, tokenRatesState, multichainRatesState, multichainBalancesState, tokensState, currencyRateState, enabledNetworkMap, period) {
261
+ const isEvmChainEnabled = (chainId) => isChainEnabledByMap(enabledNetworkMap, chainId);
262
+ const isAssetChainEnabled = (assetId) => {
263
+ const { chainId } = parseCaipAssetType(assetId);
264
+ return isChainEnabledByMap(enabledNetworkMap, chainId);
265
+ };
266
+ const getAccountChange = {
267
+ evm: (account) => sumEvmAccountChangeForPeriod(account, period, tokenBalancesState, tokensState, tokenRatesState, currencyRateState, isEvmChainEnabled),
268
+ nonEvm: (account) => sumNonEvmAccountChangeForPeriod(account, period, multichainBalancesState, multichainRatesState, isAssetChainEnabled),
269
+ };
270
+ const getFlatAccountChanges = () => Object.entries(accountTreeState.accountTree.wallets ?? {})
271
+ .flatMap(([walletId, wallet]) => Object.keys(wallet?.groups || {}).flatMap((groupId) => {
272
+ const accounts = getInternalAccountsForGroup(accountTreeState, accountsState, groupId);
273
+ return accounts.map((account) => ({
274
+ walletId,
275
+ groupId,
276
+ account,
277
+ isEvm: isEvmAccountType(account.type),
278
+ }));
279
+ }))
280
+ .map((flatAccount) => {
281
+ const flatAccountWithChange = flatAccount;
282
+ const change = flatAccount.isEvm
283
+ ? getAccountChange.evm(flatAccount.account)
284
+ : getAccountChange.nonEvm(flatAccount.account);
285
+ flatAccountWithChange.current = change.current;
286
+ flatAccountWithChange.previous = change.previous;
287
+ return flatAccountWithChange;
288
+ });
289
+ const getAggregatedTotals = (flatAccountChanges) => {
290
+ return flatAccountChanges.reduce((totals, account) => {
291
+ totals.current += account.current;
292
+ totals.previous += account.previous;
293
+ return totals;
294
+ }, { current: 0, previous: 0 });
295
+ };
296
+ const flatAccountChanges = getFlatAccountChanges();
297
+ const aggregatedTotals = getAggregatedTotals(flatAccountChanges);
298
+ const amountChange = aggregatedTotals.current - aggregatedTotals.previous;
299
+ const percentChange = aggregatedTotals.previous !== 0
300
+ ? (amountChange / aggregatedTotals.previous) * 100
301
+ : 0;
302
+ return {
303
+ period,
304
+ currentTotalInUserCurrency: Number(aggregatedTotals.current.toFixed(8)),
305
+ previousTotalInUserCurrency: Number(aggregatedTotals.previous.toFixed(8)),
306
+ amountChangeInUserCurrency: Number(amountChange.toFixed(8)),
307
+ percentChange: Number(percentChange.toFixed(8)),
308
+ userCurrency: currencyRateState.currentCurrency,
309
+ };
310
+ }
311
+ /**
312
+ * Sum EVM account change for a period (current and previous totals).
313
+ *
314
+ * @param account - Internal account to aggregate.
315
+ * @param period - Change period ('1d' | '7d' | '30d').
316
+ * @param tokenBalancesState - Token balances controller state.
317
+ * @param tokensState - Tokens controller state.
318
+ * @param tokenRatesState - Token rates controller state.
319
+ * @param currencyRateState - Currency rate controller state.
320
+ * @param isEvmChainEnabled - Predicate that returns true if the EVM chain is enabled.
321
+ * @returns Object with current and previous totals in user currency.
322
+ */
323
+ function sumEvmAccountChangeForPeriod(account, period, tokenBalancesState, tokensState, tokenRatesState, currencyRateState, isEvmChainEnabled) {
324
+ const tokenBalances = getEvmTokenBalances(account, tokenBalancesState, tokensState, tokenRatesState, currencyRateState, isEvmChainEnabled);
325
+ const tokenChanges = tokenBalances
326
+ .map((token) => {
327
+ const percentRaw = token.tokenMarketData[evmRatePropertiesRecord[period]];
328
+ if (!isNonNaNNumber(percentRaw)) {
329
+ return null;
330
+ }
331
+ const denom = Number((1 + percentRaw / 100).toFixed(8));
332
+ if (denom === 0) {
333
+ return null;
334
+ }
335
+ return {
336
+ current: token.userCurrencyValue,
337
+ previous: token.userCurrencyValue / denom,
338
+ };
339
+ })
340
+ .filter((change) => change !== null);
341
+ return tokenChanges.reduce((totals, change) => {
342
+ totals.current += change.current;
343
+ totals.previous += change.previous;
344
+ return totals;
345
+ }, { current: 0, previous: 0 });
346
+ }
347
+ /**
348
+ * Sum non-EVM account change for a period (current and previous totals).
349
+ *
350
+ * @param account - Internal account to aggregate.
351
+ * @param period - Change period ('1d' | '7d' | '30d').
352
+ * @param multichainBalancesState - Multichain balances controller state.
353
+ * @param multichainRatesState - Multichain assets rates controller state.
354
+ * @param isAssetChainEnabled - Predicate that returns true if the asset's chain is enabled.
355
+ * @returns Object with current and previous totals in user currency.
356
+ */
357
+ function sumNonEvmAccountChangeForPeriod(account, period, multichainBalancesState, multichainRatesState, isAssetChainEnabled) {
358
+ const assetBalances = getNonEvmAssetBalances(account, multichainBalancesState, multichainRatesState, isAssetChainEnabled);
359
+ const assetChanges = assetBalances
360
+ .map((asset) => {
361
+ // Safely access the percent change data with proper type checking
362
+ const marketData = asset.conversionRate?.marketData;
363
+ const pricePercentChange = marketData?.pricePercentChange;
364
+ const percentRaw = pricePercentChange?.[nonEvmRatePropertiesRecord[period]];
365
+ if (!isNonNaNNumber(percentRaw)) {
366
+ return null;
367
+ }
368
+ const denom = Number((1 + percentRaw / 100).toFixed(8));
369
+ if (denom === 0) {
370
+ return null;
371
+ }
372
+ return {
373
+ current: asset.userCurrencyValue,
374
+ previous: asset.userCurrencyValue / denom,
375
+ };
376
+ })
377
+ .filter((change) => change !== null);
378
+ return assetChanges.reduce((totals, change) => ({
379
+ current: totals.current + change.current,
380
+ previous: totals.previous + change.previous,
381
+ }), { current: 0, previous: 0 });
382
+ }
383
+ /**
384
+ * Calculate portfolio value change for a specific account group and period.
385
+ *
386
+ * @param accountTreeState - AccountTreeController state.
387
+ * @param accountsState - AccountsController state.
388
+ * @param tokenBalancesState - TokenBalancesController state.
389
+ * @param tokenRatesState - TokenRatesController state.
390
+ * @param multichainRatesState - MultichainAssetsRatesController state.
391
+ * @param multichainBalancesState - MultichainBalancesController state.
392
+ * @param tokensState - TokensController state.
393
+ * @param currencyRateState - CurrencyRateController state.
394
+ * @param enabledNetworkMap - Map of enabled networks keyed by namespace.
395
+ * @param groupId - Account group ID to compute change for.
396
+ * @param period - Change period ('1d' | '7d' | '30d').
397
+ * @returns Change result including current, previous, delta, percent, and period.
398
+ */
399
+ export function calculateBalanceChangeForAccountGroup(accountTreeState, accountsState, tokenBalancesState, tokenRatesState, multichainRatesState, multichainBalancesState, tokensState, currencyRateState, enabledNetworkMap, groupId, period) {
400
+ const isEvmChainEnabled = (chainId) => isChainEnabledByMap(enabledNetworkMap, chainId);
401
+ const isAssetChainEnabled = (assetId) => {
402
+ const { chainId } = parseCaipAssetType(assetId);
403
+ return isChainEnabledByMap(enabledNetworkMap, chainId);
404
+ };
405
+ const getAccountChange = {
406
+ evm: (account) => sumEvmAccountChangeForPeriod(account, period, tokenBalancesState, tokensState, tokenRatesState, currencyRateState, isEvmChainEnabled),
407
+ nonEvm: (account) => sumNonEvmAccountChangeForPeriod(account, period, multichainBalancesState, multichainRatesState, isAssetChainEnabled),
408
+ };
409
+ const getFlatAccountChanges = () => {
410
+ const accounts = getInternalAccountsForGroup(accountTreeState, accountsState, groupId);
411
+ return accounts.map((account) => ({
412
+ account,
413
+ isEvm: isEvmAccountType(account.type),
414
+ }));
415
+ };
416
+ const getAggregatedTotals = (flatAccountChanges) => {
417
+ return flatAccountChanges.reduce((totals, { account, isEvm }) => {
418
+ const change = isEvm
419
+ ? getAccountChange.evm(account)
420
+ : getAccountChange.nonEvm(account);
421
+ totals.current += change.current;
422
+ totals.previous += change.previous;
423
+ return totals;
424
+ }, { current: 0, previous: 0 });
425
+ };
426
+ const flatAccountChanges = getFlatAccountChanges();
427
+ const aggregatedTotals = getAggregatedTotals(flatAccountChanges);
428
+ const amountChange = aggregatedTotals.current - aggregatedTotals.previous;
429
+ const percentChange = aggregatedTotals.previous !== 0
430
+ ? (amountChange / aggregatedTotals.previous) * 100
431
+ : 0;
432
+ return {
433
+ period,
434
+ currentTotalInUserCurrency: Number(aggregatedTotals.current.toFixed(8)),
435
+ previousTotalInUserCurrency: Number(aggregatedTotals.previous.toFixed(8)),
436
+ amountChangeInUserCurrency: Number(amountChange.toFixed(8)),
437
+ percentChange: Number(percentChange.toFixed(8)),
438
+ userCurrency: currencyRateState.currentCurrency,
439
+ };
440
+ }
441
+ //# sourceMappingURL=balances.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balances.mjs","sourceRoot":"","sources":["../src/balances.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport type { AccountTreeControllerState } from '@metamask/account-tree-controller';\nimport type { AccountsControllerState } from '@metamask/accounts-controller';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Hex } from '@metamask/utils';\nimport type { CaipAssetType, CaipChainId } from '@metamask/utils';\nimport {\n KnownCaipNamespace,\n parseCaipAssetType,\n parseCaipChainId,\n isStrictHexString,\n} from '@metamask/utils';\n\nimport type { CurrencyRateState } from './CurrencyRateController';\nimport type { MultichainAssetsRatesControllerState } from './MultichainAssetsRatesController';\nimport type { MultichainBalancesControllerState } from './MultichainBalancesController';\nimport type { TokenBalancesControllerState } from './TokenBalancesController';\nimport type { TokenRatesControllerState } from './TokenRatesController';\nimport type { TokensControllerState } from './TokensController';\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\nconst evmRatePropertiesRecord = {\n '1d': 'pricePercentChange1d',\n '7d': 'pricePercentChange7d',\n '30d': 'pricePercentChange30d',\n} as const;\n\nconst nonEvmRatePropertiesRecord = {\n '1d': 'P1D',\n '7d': 'P7D',\n '30d': 'P30D',\n};\n\nexport type BalanceChangeResult = {\n period: BalanceChangePeriod;\n currentTotalInUserCurrency: number;\n previousTotalInUserCurrency: number;\n amountChangeInUserCurrency: number;\n percentChange: number;\n userCurrency: string;\n};\n\nconst isChainEnabledByMap = (\n map: Record<string, Record<string, boolean>> | undefined,\n id: Hex | CaipChainId,\n): boolean => {\n if (!map) {\n return true;\n }\n if (isStrictHexString(id)) {\n return Boolean(map[KnownCaipNamespace.Eip155]?.[id]);\n }\n const { namespace } = parseCaipChainId(id);\n return Boolean(map[namespace]?.[id]);\n};\n\nconst getWalletIdFromGroupId = (groupId: string): AccountWalletId => {\n return groupId.split('/')[0] as AccountWalletId;\n};\n\nconst getInternalAccountsForGroup = (\n accountTreeState: AccountTreeControllerState,\n accountsState: AccountsControllerState,\n groupId: string,\n): InternalAccount[] => {\n const walletId = getWalletIdFromGroupId(groupId);\n const wallet = accountTreeState.accountTree.wallets[walletId];\n if (!wallet) {\n return [];\n }\n const group = wallet.groups[groupId as AccountGroupId];\n if (!group) {\n return [];\n }\n return group.accounts\n .map(\n (accountId: string) => accountsState.internalAccounts.accounts[accountId],\n )\n .filter(Boolean);\n};\n\nconst isNonNaNNumber = (value: unknown): value is number =>\n typeof value === 'number' && !Number.isNaN(value);\n\n/**\n * Combined function that gets valid token balances with calculation data\n *\n * @param account - Internal account.\n * @param tokenBalancesState - Token balances state.\n * @param tokensState - Tokens state.\n * @param tokenRatesState - Token rates state.\n * @param currencyRateState - Currency rate state.\n * @param isEvmChainEnabled - Predicate to check EVM chain enablement.\n * @returns token calculation data\n */\nfunction getEvmTokenBalances(\n account: InternalAccount,\n tokenBalancesState: TokenBalancesControllerState,\n tokensState: TokensControllerState,\n tokenRatesState: TokenRatesControllerState,\n currencyRateState: CurrencyRateState,\n isEvmChainEnabled: (chainId: Hex) => boolean,\n) {\n const accountBalances =\n tokenBalancesState.tokenBalances[account.address as Hex] ?? {};\n\n return Object.entries(accountBalances)\n .filter(([chainId]) => isEvmChainEnabled(chainId as Hex))\n .flatMap(([chainId, chainBalances]) =>\n Object.entries(chainBalances).map(([tokenAddress, balance]) => ({\n chainId: chainId as Hex,\n tokenAddress: tokenAddress as Hex,\n balance,\n })),\n )\n .map((tokenBalance) => {\n const { chainId, tokenAddress, balance } = tokenBalance;\n\n // Get Token Info\n const accountTokens =\n tokensState?.allTokens?.[chainId]?.[account.address];\n const token = accountTokens?.find((t) => t.address === tokenAddress);\n if (!token) {\n return null;\n }\n\n // Get market data\n const tokenMarketData =\n tokenRatesState?.marketData?.[chainId]?.[tokenAddress];\n if (!tokenMarketData?.price) {\n return null;\n }\n\n // Get conversion rate\n const nativeToUserRate =\n currencyRateState.currencyRates[tokenMarketData.currency]\n ?.conversionRate;\n if (!nativeToUserRate) {\n return null;\n }\n\n // Calculate values\n const decimals = isNonNaNNumber(token.decimals) ? token.decimals : 18;\n const decimalBalance = parseInt(balance, 16);\n if (!isNonNaNNumber(decimalBalance)) {\n return null;\n }\n\n const userCurrencyValue =\n (decimalBalance / Math.pow(10, decimals)) *\n tokenMarketData.price *\n nativeToUserRate;\n\n return {\n userCurrencyValue,\n tokenMarketData, // Only needed for change calculations\n };\n })\n .filter((item): item is NonNullable<typeof item> => item !== null);\n}\n\n/**\n * Combined function that gets valid non-EVM asset balances with calculation data\n *\n * @param account - Internal account.\n * @param multichainBalancesState - Multichain balances state.\n * @param multichainRatesState - Multichain rates state.\n * @param isAssetChainEnabled - Predicate to check asset chain enablement.\n * @returns token calculation data\n */\nfunction getNonEvmAssetBalances(\n account: InternalAccount,\n multichainBalancesState: MultichainBalancesControllerState,\n multichainRatesState: MultichainAssetsRatesControllerState,\n isAssetChainEnabled: (assetId: CaipAssetType) => boolean,\n) {\n const accountBalances = multichainBalancesState.balances[account.id] ?? {};\n\n return Object.entries(accountBalances)\n .filter(([assetId]) => isAssetChainEnabled(assetId as CaipAssetType))\n .map(([assetId, balanceData]) => {\n const balanceAmount = parseFloat(balanceData.amount);\n if (Number.isNaN(balanceAmount)) {\n return null;\n }\n\n const conversionRate =\n multichainRatesState.conversionRates[assetId as CaipAssetType];\n if (!conversionRate) {\n return null;\n }\n\n const conversionRateValue = parseFloat(conversionRate.rate);\n if (Number.isNaN(conversionRateValue)) {\n return null;\n }\n\n const userCurrencyValue = balanceAmount * conversionRateValue;\n\n return {\n assetId: assetId as CaipAssetType,\n userCurrencyValue,\n conversionRate, // Only needed for change calculations\n };\n })\n .filter((item): item is NonNullable<typeof item> => item !== null);\n}\n\n/**\n * Sum EVM account token balances in user currency.\n *\n * @param account - Internal account.\n * @param tokenBalancesState - Token balances state.\n * @param tokensState - Tokens state.\n * @param tokenRatesState - Token rates state.\n * @param currencyRateState - Currency rate state.\n * @param isEvmChainEnabled - Predicate to check EVM chain enablement.\n * @returns Total value in user currency.\n */\nfunction sumEvmAccountBalanceInUserCurrency(\n account: InternalAccount,\n tokenBalancesState: TokenBalancesControllerState,\n tokensState: TokensControllerState,\n tokenRatesState: TokenRatesControllerState,\n currencyRateState: CurrencyRateState,\n isEvmChainEnabled: (chainId: Hex) => boolean,\n): number {\n const tokenBalances = getEvmTokenBalances(\n account,\n tokenBalancesState,\n tokensState,\n tokenRatesState,\n currencyRateState,\n isEvmChainEnabled,\n );\n return tokenBalances.reduce((a, b) => a + b.userCurrencyValue, 0);\n}\n\n/**\n * Sum non‑EVM account balances in user currency from multichain sources.\n *\n * @param account - Internal account.\n * @param multichainBalancesState - Multichain balances state.\n * @param multichainRatesState - Multichain rates state.\n * @param isAssetChainEnabled - Predicate to check asset chain enablement.\n * @returns Total value in user currency.\n */\nfunction sumNonEvmAccountBalanceInUserCurrency(\n account: InternalAccount,\n multichainBalancesState: MultichainBalancesControllerState,\n multichainRatesState: MultichainAssetsRatesControllerState,\n isAssetChainEnabled: (assetId: CaipAssetType) => boolean,\n): number {\n const assetBalances = getNonEvmAssetBalances(\n account,\n multichainBalancesState,\n multichainRatesState,\n isAssetChainEnabled,\n );\n\n return assetBalances.reduce((a, b) => a + b.userCurrencyValue, 0);\n}\n\n/**\n * Calculate balances for all wallets and groups.\n * Pure function – accepts controller states and returns aggregated totals.\n *\n * @param accountTreeState - AccountTreeController state\n * @param accountsState - AccountsController state\n * @param tokenBalancesState - TokenBalancesController state\n * @param tokenRatesState - TokenRatesController state\n * @param multichainRatesState - MultichainAssetsRatesController state\n * @param multichainBalancesState - MultichainBalancesController state\n * @param tokensState - TokensController state\n * @param currencyRateState - CurrencyRateController state\n * @param enabledNetworkMap - Map of enabled networks keyed by namespace\n * @returns Aggregated balances for all wallets\n */\nexport function calculateBalanceForAllWallets(\n accountTreeState: AccountTreeControllerState,\n accountsState: AccountsControllerState,\n tokenBalancesState: TokenBalancesControllerState,\n tokenRatesState: TokenRatesControllerState,\n multichainRatesState: MultichainAssetsRatesControllerState,\n multichainBalancesState: MultichainBalancesControllerState,\n tokensState: TokensControllerState,\n currencyRateState: CurrencyRateState,\n enabledNetworkMap: Record<string, Record<string, boolean>> | undefined,\n): AllWalletsBalance {\n const isEvmChainEnabled = (chainId: Hex): boolean =>\n isChainEnabledByMap(enabledNetworkMap, chainId);\n\n const isAssetChainEnabled = (assetId: CaipAssetType): boolean =>\n isChainEnabledByMap(enabledNetworkMap, parseCaipAssetType(assetId).chainId);\n\n const getBalance = {\n evm: (account: InternalAccount) =>\n sumEvmAccountBalanceInUserCurrency(\n account,\n tokenBalancesState,\n tokensState,\n tokenRatesState,\n currencyRateState,\n isEvmChainEnabled,\n ),\n nonEvm: (account: InternalAccount) =>\n sumNonEvmAccountBalanceInUserCurrency(\n account,\n multichainBalancesState,\n multichainRatesState,\n isAssetChainEnabled,\n ),\n };\n\n const getFlatAccountBalances = () =>\n Object.entries(accountTreeState.accountTree.wallets ?? {})\n .flatMap(([walletId, wallet]) =>\n Object.keys(wallet?.groups || {}).flatMap((groupId) => {\n const accounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsState,\n groupId,\n );\n\n return accounts.map((account) => ({\n walletId,\n groupId,\n account,\n isEvm: isEvmAccountType(account.type),\n }));\n }),\n )\n .map((flatAccount) => {\n const flatAccountWithBalance = flatAccount as typeof flatAccount & {\n balance: number;\n };\n flatAccountWithBalance.balance = flatAccount.isEvm\n ? getBalance.evm(flatAccount.account)\n : getBalance.nonEvm(flatAccount.account);\n return flatAccountWithBalance;\n });\n\n const getAggWalletBalance = (\n flatAccountBalances: ReturnType<typeof getFlatAccountBalances>,\n ): number => flatAccountBalances.reduce((a, b) => a + b.balance, 0);\n\n const getWalletBalances = (\n flatAccountBalances: ReturnType<typeof getFlatAccountBalances>,\n ): Record<string, WalletBalance> => {\n const wallets: Record<string, WalletBalance> = {};\n const defaultWalletBalance = (walletId: string): WalletBalance => ({\n walletId,\n groups: {},\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n });\n const defaultGroupBalance = (\n walletId: string,\n groupId: string,\n ): AccountGroupBalance => ({\n walletId,\n groupId,\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n });\n\n flatAccountBalances.forEach((flatAccount) => {\n const { walletId, groupId, balance } = flatAccount;\n wallets[walletId] ??= defaultWalletBalance(walletId);\n wallets[walletId].groups[groupId] ??= defaultGroupBalance(\n walletId,\n groupId,\n );\n wallets[walletId].groups[groupId].totalBalanceInUserCurrency += balance;\n wallets[walletId].totalBalanceInUserCurrency += balance;\n });\n\n // Ensure all groups (including empty ones) are represented\n Object.entries(accountTreeState.accountTree.wallets ?? {}).forEach(\n ([walletId, wallet]) => {\n if (!wallet) {\n return;\n }\n wallets[walletId] ??= defaultWalletBalance(walletId);\n Object.keys(wallet.groups || {}).forEach((groupId) => {\n wallets[walletId].groups[groupId] ??= defaultGroupBalance(\n walletId,\n groupId,\n );\n });\n },\n );\n\n return wallets;\n };\n\n const flatAccounts = getFlatAccountBalances();\n return {\n wallets: getWalletBalances(flatAccounts),\n totalBalanceInUserCurrency: getAggWalletBalance(flatAccounts),\n userCurrency: currencyRateState.currentCurrency,\n };\n}\n\n/**\n * Calculate aggregated portfolio value change for a given period (1d, 7d, 30d).\n * Logic mirrors extension/mobile historical aggregation:\n * - For each asset with available percent change for the requested period, compute current value in user currency.\n * - Reconstruct previous value by dividing current by (1 + percent/100).\n * - Sum across all assets, then compute amount change and percent change.\n *\n * @param accountTreeState - AccountTreeController state.\n * @param accountsState - AccountsController state.\n * @param tokenBalancesState - TokenBalancesController state.\n * @param tokenRatesState - TokenRatesController state.\n * @param multichainRatesState - MultichainAssetsRatesController state.\n * @param multichainBalancesState - MultichainBalancesController state.\n * @param tokensState - TokensController state.\n * @param currencyRateState - CurrencyRateController state.\n * @param enabledNetworkMap - Map of enabled networks keyed by namespace.\n * @param period - Period to compute change for ('1d' | '7d' | '30d').\n * @returns Aggregated change details for the requested period.\n */\nexport function calculateBalanceChangeForAllWallets(\n accountTreeState: AccountTreeControllerState,\n accountsState: AccountsControllerState,\n tokenBalancesState: TokenBalancesControllerState,\n tokenRatesState: TokenRatesControllerState,\n multichainRatesState: MultichainAssetsRatesControllerState,\n multichainBalancesState: MultichainBalancesControllerState,\n tokensState: TokensControllerState,\n currencyRateState: CurrencyRateState,\n enabledNetworkMap: Record<string, Record<string, boolean>> | undefined,\n period: BalanceChangePeriod,\n): BalanceChangeResult {\n const isEvmChainEnabled = (chainId: Hex): boolean =>\n isChainEnabledByMap(enabledNetworkMap, chainId);\n\n const isAssetChainEnabled = (assetId: CaipAssetType): boolean => {\n const { chainId } = parseCaipAssetType(assetId);\n return isChainEnabledByMap(enabledNetworkMap, chainId);\n };\n\n const getAccountChange = {\n evm: (account: InternalAccount) =>\n sumEvmAccountChangeForPeriod(\n account,\n period,\n tokenBalancesState,\n tokensState,\n tokenRatesState,\n currencyRateState,\n isEvmChainEnabled,\n ),\n nonEvm: (account: InternalAccount) =>\n sumNonEvmAccountChangeForPeriod(\n account,\n period,\n multichainBalancesState,\n multichainRatesState,\n isAssetChainEnabled,\n ),\n };\n\n const getFlatAccountChanges = () =>\n Object.entries(accountTreeState.accountTree.wallets ?? {})\n .flatMap(([walletId, wallet]) =>\n Object.keys(wallet?.groups || {}).flatMap((groupId) => {\n const accounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsState,\n groupId,\n );\n return accounts.map((account) => ({\n walletId,\n groupId,\n account,\n isEvm: isEvmAccountType(account.type),\n }));\n }),\n )\n .map((flatAccount) => {\n const flatAccountWithChange = flatAccount as typeof flatAccount & {\n current: number;\n previous: number;\n };\n\n const change = flatAccount.isEvm\n ? getAccountChange.evm(flatAccount.account)\n : getAccountChange.nonEvm(flatAccount.account);\n\n flatAccountWithChange.current = change.current;\n flatAccountWithChange.previous = change.previous;\n return flatAccountWithChange;\n });\n\n const getAggregatedTotals = (\n flatAccountChanges: ReturnType<typeof getFlatAccountChanges>,\n ) => {\n return flatAccountChanges.reduce(\n (totals, account) => {\n totals.current += account.current;\n totals.previous += account.previous;\n return totals;\n },\n { current: 0, previous: 0 },\n );\n };\n\n const flatAccountChanges = getFlatAccountChanges();\n const aggregatedTotals = getAggregatedTotals(flatAccountChanges);\n const amountChange = aggregatedTotals.current - aggregatedTotals.previous;\n const percentChange =\n aggregatedTotals.previous !== 0\n ? (amountChange / aggregatedTotals.previous) * 100\n : 0;\n\n return {\n period,\n currentTotalInUserCurrency: Number(aggregatedTotals.current.toFixed(8)),\n previousTotalInUserCurrency: Number(aggregatedTotals.previous.toFixed(8)),\n amountChangeInUserCurrency: Number(amountChange.toFixed(8)),\n percentChange: Number(percentChange.toFixed(8)),\n userCurrency: currencyRateState.currentCurrency,\n };\n}\n\n/**\n * Sum EVM account change for a period (current and previous totals).\n *\n * @param account - Internal account to aggregate.\n * @param period - Change period ('1d' | '7d' | '30d').\n * @param tokenBalancesState - Token balances controller state.\n * @param tokensState - Tokens controller state.\n * @param tokenRatesState - Token rates controller state.\n * @param currencyRateState - Currency rate controller state.\n * @param isEvmChainEnabled - Predicate that returns true if the EVM chain is enabled.\n * @returns Object with current and previous totals in user currency.\n */\nfunction sumEvmAccountChangeForPeriod(\n account: InternalAccount,\n period: BalanceChangePeriod,\n tokenBalancesState: TokenBalancesControllerState,\n tokensState: TokensControllerState,\n tokenRatesState: TokenRatesControllerState,\n currencyRateState: CurrencyRateState,\n isEvmChainEnabled: (chainId: Hex) => boolean,\n): { current: number; previous: number } {\n const tokenBalances = getEvmTokenBalances(\n account,\n tokenBalancesState,\n tokensState,\n tokenRatesState,\n currencyRateState,\n isEvmChainEnabled,\n );\n\n const tokenChanges = tokenBalances\n .map((token) => {\n const percentRaw = token.tokenMarketData[evmRatePropertiesRecord[period]];\n if (!isNonNaNNumber(percentRaw)) {\n return null;\n }\n\n const denom = Number((1 + percentRaw / 100).toFixed(8));\n if (denom === 0) {\n return null;\n }\n\n return {\n current: token.userCurrencyValue,\n previous: token.userCurrencyValue / denom,\n };\n })\n .filter((change): change is NonNullable<typeof change> => change !== null);\n\n return tokenChanges.reduce(\n (totals, change) => {\n totals.current += change.current;\n totals.previous += change.previous;\n return totals;\n },\n { current: 0, previous: 0 },\n );\n}\n\n/**\n * Sum non-EVM account change for a period (current and previous totals).\n *\n * @param account - Internal account to aggregate.\n * @param period - Change period ('1d' | '7d' | '30d').\n * @param multichainBalancesState - Multichain balances controller state.\n * @param multichainRatesState - Multichain assets rates controller state.\n * @param isAssetChainEnabled - Predicate that returns true if the asset's chain is enabled.\n * @returns Object with current and previous totals in user currency.\n */\nfunction sumNonEvmAccountChangeForPeriod(\n account: InternalAccount,\n period: BalanceChangePeriod,\n multichainBalancesState: MultichainBalancesControllerState,\n multichainRatesState: MultichainAssetsRatesControllerState,\n isAssetChainEnabled: (assetId: CaipAssetType) => boolean,\n): { current: number; previous: number } {\n const assetBalances = getNonEvmAssetBalances(\n account,\n multichainBalancesState,\n multichainRatesState,\n isAssetChainEnabled,\n );\n\n const assetChanges = assetBalances\n .map((asset) => {\n // Safely access the percent change data with proper type checking\n const marketData = asset.conversionRate?.marketData;\n const pricePercentChange = marketData?.pricePercentChange;\n const percentRaw =\n pricePercentChange?.[nonEvmRatePropertiesRecord[period]];\n\n if (!isNonNaNNumber(percentRaw)) {\n return null;\n }\n\n const denom = Number((1 + percentRaw / 100).toFixed(8));\n if (denom === 0) {\n return null;\n }\n\n return {\n current: asset.userCurrencyValue,\n previous: asset.userCurrencyValue / denom,\n };\n })\n .filter((change): change is NonNullable<typeof change> => change !== null);\n\n return assetChanges.reduce(\n (totals, change) => ({\n current: totals.current + change.current,\n previous: totals.previous + change.previous,\n }),\n { current: 0, previous: 0 },\n );\n}\n\n/**\n * Calculate portfolio value change for a specific account group and period.\n *\n * @param accountTreeState - AccountTreeController state.\n * @param accountsState - AccountsController state.\n * @param tokenBalancesState - TokenBalancesController state.\n * @param tokenRatesState - TokenRatesController state.\n * @param multichainRatesState - MultichainAssetsRatesController state.\n * @param multichainBalancesState - MultichainBalancesController state.\n * @param tokensState - TokensController state.\n * @param currencyRateState - CurrencyRateController state.\n * @param enabledNetworkMap - Map of enabled networks keyed by namespace.\n * @param groupId - Account group ID to compute change for.\n * @param period - Change period ('1d' | '7d' | '30d').\n * @returns Change result including current, previous, delta, percent, and period.\n */\nexport function calculateBalanceChangeForAccountGroup(\n accountTreeState: AccountTreeControllerState,\n accountsState: AccountsControllerState,\n tokenBalancesState: TokenBalancesControllerState,\n tokenRatesState: TokenRatesControllerState,\n multichainRatesState: MultichainAssetsRatesControllerState,\n multichainBalancesState: MultichainBalancesControllerState,\n tokensState: TokensControllerState,\n currencyRateState: CurrencyRateState,\n enabledNetworkMap: Record<string, Record<string, boolean>> | undefined,\n groupId: string,\n period: BalanceChangePeriod,\n): BalanceChangeResult {\n const isEvmChainEnabled = (chainId: Hex): boolean =>\n isChainEnabledByMap(enabledNetworkMap, chainId);\n\n const isAssetChainEnabled = (assetId: CaipAssetType): boolean => {\n const { chainId } = parseCaipAssetType(assetId);\n return isChainEnabledByMap(enabledNetworkMap, chainId);\n };\n\n const getAccountChange = {\n evm: (account: InternalAccount) =>\n sumEvmAccountChangeForPeriod(\n account,\n period,\n tokenBalancesState,\n tokensState,\n tokenRatesState,\n currencyRateState,\n isEvmChainEnabled,\n ),\n nonEvm: (account: InternalAccount) =>\n sumNonEvmAccountChangeForPeriod(\n account,\n period,\n multichainBalancesState,\n multichainRatesState,\n isAssetChainEnabled,\n ),\n };\n\n const getFlatAccountChanges = () => {\n const accounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsState,\n groupId,\n );\n return accounts.map((account) => ({\n account,\n isEvm: isEvmAccountType(account.type),\n }));\n };\n\n const getAggregatedTotals = (\n flatAccountChanges: ReturnType<typeof getFlatAccountChanges>,\n ) => {\n return flatAccountChanges.reduce(\n (totals, { account, isEvm }) => {\n const change = isEvm\n ? getAccountChange.evm(account)\n : getAccountChange.nonEvm(account);\n totals.current += change.current;\n totals.previous += change.previous;\n return totals;\n },\n { current: 0, previous: 0 },\n );\n };\n\n const flatAccountChanges = getFlatAccountChanges();\n const aggregatedTotals = getAggregatedTotals(flatAccountChanges);\n\n const amountChange = aggregatedTotals.current - aggregatedTotals.previous;\n const percentChange =\n aggregatedTotals.previous !== 0\n ? (amountChange / aggregatedTotals.previous) * 100\n : 0;\n\n return {\n period,\n currentTotalInUserCurrency: Number(aggregatedTotals.current.toFixed(8)),\n previousTotalInUserCurrency: Number(aggregatedTotals.previous.toFixed(8)),\n amountChangeInUserCurrency: Number(amountChange.toFixed(8)),\n percentChange: Number(percentChange.toFixed(8)),\n userCurrency: currencyRateState.currentCurrency,\n };\n}\n"]}
@@ -1,10 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Source = void 0;
3
+ exports.SUPPORTED_NETWORKS_ACCOUNTS_API_V4 = exports.Source = void 0;
4
4
  var Source;
5
5
  (function (Source) {
6
6
  Source["Custom"] = "custom";
7
7
  Source["Dapp"] = "dapp";
8
8
  Source["Detected"] = "detected";
9
9
  })(Source || (exports.Source = Source = {}));
10
+ // TODO: delete this once we have the v4 endpoint for supported networks
11
+ exports.SUPPORTED_NETWORKS_ACCOUNTS_API_V4 = [
12
+ '0x1',
13
+ '0x89',
14
+ '0x38',
15
+ '0xe728',
16
+ '0x2105',
17
+ '0xa',
18
+ '0xa4b1',
19
+ '0x82750',
20
+ '0x531', // 1329
21
+ ];
10
22
  //# sourceMappingURL=constants.cjs.map