@metamask-previews/assets-controllers 73.0.1-preview-2e90d98e → 73.0.1-preview-e4e5ca5c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/selectors/balanceSelectors.cjs +27 -34
- package/dist/selectors/balanceSelectors.cjs.map +1 -1
- package/dist/selectors/balanceSelectors.d.cts.map +1 -1
- package/dist/selectors/balanceSelectors.d.mts.map +1 -1
- package/dist/selectors/balanceSelectors.mjs +27 -34
- package/dist/selectors/balanceSelectors.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -28,28 +28,6 @@ const getInternalAccountsForGroup = (accountTreeState, accountsState, groupId) =
|
|
|
28
28
|
.map((accountId) => accountsState.internalAccounts.accounts[accountId])
|
|
29
29
|
.filter(Boolean);
|
|
30
30
|
};
|
|
31
|
-
/**
|
|
32
|
-
* Helper function to convert USD amount to user's selected currency
|
|
33
|
-
*
|
|
34
|
-
* @param usdAmount - Amount in USD
|
|
35
|
-
* @param currencyRateState - CurrencyRateController state
|
|
36
|
-
* @returns Amount converted to user's selected currency
|
|
37
|
-
*/
|
|
38
|
-
const convertUsdToUserCurrency = (usdAmount, currencyRateState) => {
|
|
39
|
-
// If user currency is USD, no conversion needed
|
|
40
|
-
if (currencyRateState.currentCurrency.toLowerCase() === 'usd') {
|
|
41
|
-
return usdAmount;
|
|
42
|
-
}
|
|
43
|
-
// Get USD conversion rate for the user's currency
|
|
44
|
-
// We need to find a currency that has usdConversionRate set
|
|
45
|
-
const currencyWithUsdRate = Object.values(currencyRateState.currencyRates).find((rate) => rate.usdConversionRate !== null);
|
|
46
|
-
if (!currencyWithUsdRate?.usdConversionRate) {
|
|
47
|
-
// If no USD conversion rate is available, return USD amount as fallback
|
|
48
|
-
return usdAmount;
|
|
49
|
-
}
|
|
50
|
-
// Convert USD to user currency using the USD conversion rate
|
|
51
|
-
return usdAmount * currencyWithUsdRate.usdConversionRate;
|
|
52
|
-
};
|
|
53
31
|
/**
|
|
54
32
|
* Selector to get aggregated balances for a specific account group.
|
|
55
33
|
* Returns total balance in user's selected currency, aggregating all tokens across accounts in the group.
|
|
@@ -78,7 +56,7 @@ const selectBalanceByAccountGroup = (groupId) => (0, reselect_1.createSelector)(
|
|
|
78
56
|
userCurrency: currencyRateState.currentCurrency,
|
|
79
57
|
};
|
|
80
58
|
}
|
|
81
|
-
let
|
|
59
|
+
let totalBalanceInUserCurrency = 0;
|
|
82
60
|
// Process each account's balances
|
|
83
61
|
for (const account of accounts) {
|
|
84
62
|
const isEvmAccount = (0, keyring_api_1.isEvmAccountType)(account.type);
|
|
@@ -98,18 +76,25 @@ const selectBalanceByAccountGroup = (groupId) => (0, reselect_1.createSelector)(
|
|
|
98
76
|
}
|
|
99
77
|
const decimals = token.decimals || 18;
|
|
100
78
|
const balanceInSmallestUnit = parseInt(balance, 16);
|
|
79
|
+
// Skip invalid balance values to prevent NaN propagation
|
|
80
|
+
if (Number.isNaN(balanceInSmallestUnit)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
101
83
|
const balanceInTokenUnits = balanceInSmallestUnit / Math.pow(10, decimals);
|
|
102
84
|
// Get token rate in native currency from TokenRatesController
|
|
103
85
|
const chainMarketData = tokenRatesState.marketData[chainId];
|
|
104
86
|
const tokenMarketData = chainMarketData?.[tokenAddress];
|
|
105
87
|
if (tokenMarketData?.price) {
|
|
106
|
-
// Convert
|
|
88
|
+
// Convert token price to user currency using native currency conversion rate
|
|
107
89
|
const nativeCurrency = tokenMarketData.currency;
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
90
|
+
const nativeToUserRate = currencyRateState.currencyRates[nativeCurrency]
|
|
91
|
+
?.conversionRate;
|
|
92
|
+
if (nativeToUserRate) {
|
|
93
|
+
// Convert token price to user currency: tokenPrice * nativeToUserRate
|
|
94
|
+
const tokenPriceInUserCurrency = tokenMarketData.price * nativeToUserRate;
|
|
95
|
+
const balanceInUserCurrency = balanceInTokenUnits * tokenPriceInUserCurrency;
|
|
96
|
+
totalBalanceInUserCurrency += balanceInUserCurrency;
|
|
97
|
+
}
|
|
113
98
|
}
|
|
114
99
|
}
|
|
115
100
|
}
|
|
@@ -121,18 +106,26 @@ const selectBalanceByAccountGroup = (groupId) => (0, reselect_1.createSelector)(
|
|
|
121
106
|
if (accountBalances) {
|
|
122
107
|
for (const [assetId, balanceData] of Object.entries(accountBalances)) {
|
|
123
108
|
const balanceAmount = parseFloat(balanceData.amount);
|
|
124
|
-
//
|
|
109
|
+
// Skip invalid balance values to prevent NaN propagation
|
|
110
|
+
if (Number.isNaN(balanceAmount)) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
// Get conversion rate for this asset (already in user currency)
|
|
125
114
|
const conversionRate = multichainRatesState.conversionRates[assetId];
|
|
126
115
|
if (conversionRate) {
|
|
127
|
-
const
|
|
128
|
-
|
|
116
|
+
const conversionRateValue = parseFloat(conversionRate.rate);
|
|
117
|
+
// Skip invalid conversion rate values to prevent NaN propagation
|
|
118
|
+
if (Number.isNaN(conversionRateValue)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
// MultichainAssetsRatesController already provides rates in user currency
|
|
122
|
+
const balanceInUserCurrency = balanceAmount * conversionRateValue;
|
|
123
|
+
totalBalanceInUserCurrency += balanceInUserCurrency;
|
|
129
124
|
}
|
|
130
125
|
}
|
|
131
126
|
}
|
|
132
127
|
}
|
|
133
128
|
}
|
|
134
|
-
// Convert USD balance to user's selected currency
|
|
135
|
-
const totalBalanceInUserCurrency = convertUsdToUserCurrency(totalBalanceInUSD, currencyRateState);
|
|
136
129
|
return {
|
|
137
130
|
walletId,
|
|
138
131
|
groupId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balanceSelectors.cjs","sourceRoot":"","sources":["../../src/selectors/balanceSelectors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountTreeControllerState } from '@metamask/account-tree-controller';\nimport type { AccountWalletObject } from '@metamask/account-tree-controller';\nimport type { AccountGroupObject } from '@metamask/account-tree-controller';\nimport type { AccountsControllerState } from '@metamask/accounts-controller';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { Hex } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\nimport { createSelector } from 'reselect';\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\n/**\n * Root state type for all controllers used in selectors\n */\nexport type RootState = {\n TokenBalancesController: TokenBalancesControllerState;\n CurrencyRateController: CurrencyRateState;\n TokenRatesController: TokenRatesControllerState;\n MultichainAssetsRatesController: MultichainAssetsRatesControllerState;\n MultichainBalancesController: MultichainBalancesControllerState;\n TokensController: TokensControllerState;\n AccountsController: AccountsControllerState;\n AccountTreeController: AccountTreeControllerState;\n};\n\n/**\n * Helper function to get internal accounts for a specific group.\n * Uses AccountTreeController state to find accounts.\n *\n * @param accountTreeState - AccountTreeController state\n * @param accountsState - AccountsController state\n * @param groupId - The account group ID (format: \"walletId/groupIndex\")\n * @returns Array of internal accounts in the group\n */\nconst getInternalAccountsForGroup = (\n accountTreeState: AccountTreeControllerState,\n accountsState: AccountsControllerState,\n groupId: string,\n) => {\n // Extract walletId from groupId (format: \"walletId/groupIndex\")\n const walletId = groupId.split('/')[0] as EntropySourceId;\n\n const wallet = (\n accountTreeState.accountTree.wallets as Record<string, AccountWalletObject>\n )[walletId];\n if (!wallet) {\n return [];\n }\n\n const group = (wallet.groups as Record<string, AccountGroupObject>)[groupId];\n if (!group) {\n return [];\n }\n\n // Map account IDs to actual account objects\n return group.accounts\n .map(\n (accountId: string) => accountsState.internalAccounts.accounts[accountId],\n )\n .filter(Boolean);\n};\n\n/**\n * Helper function to convert USD amount to user's selected currency\n *\n * @param usdAmount - Amount in USD\n * @param currencyRateState - CurrencyRateController state\n * @returns Amount converted to user's selected currency\n */\nconst convertUsdToUserCurrency = (\n usdAmount: number,\n currencyRateState: CurrencyRateState,\n): number => {\n // If user currency is USD, no conversion needed\n if (currencyRateState.currentCurrency.toLowerCase() === 'usd') {\n return usdAmount;\n }\n\n // Get USD conversion rate for the user's currency\n // We need to find a currency that has usdConversionRate set\n const currencyWithUsdRate = Object.values(\n currencyRateState.currencyRates,\n ).find((rate) => rate.usdConversionRate !== null);\n\n if (!currencyWithUsdRate?.usdConversionRate) {\n // If no USD conversion rate is available, return USD amount as fallback\n return usdAmount;\n }\n\n // Convert USD to user currency using the USD conversion rate\n return usdAmount * currencyWithUsdRate.usdConversionRate;\n};\n\n/**\n * Selector to get aggregated balances for a specific account group.\n * Returns total balance in user's selected currency, aggregating all tokens across accounts in the group.\n *\n * @param groupId - The account group ID (format: \"walletId/groupIndex\", e.g., \"entropy:entropy-source-1/0\")\n * @returns Aggregated balance for the account group\n */\nexport const selectBalanceByAccountGroup = (groupId: string) =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AccountGroupBalance => {\n // Extract walletId from groupId\n const walletId = groupId.split('/')[0] as EntropySourceId;\n\n const accounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsState,\n groupId,\n );\n\n if (accounts.length === 0) {\n return {\n walletId,\n groupId,\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n };\n }\n\n let totalBalanceInUSD = 0;\n\n // Process each account's balances\n for (const account of accounts) {\n const isEvmAccount = isEvmAccountType(account.type);\n\n if (isEvmAccount) {\n // Handle EVM account balances from TokenBalancesController\n // Structure: tokenBalances[chainId][accountAddress][tokenAddress] = balance\n for (const [chainId, chainBalances] of Object.entries(\n tokenBalancesState.tokenBalances,\n )) {\n const accountBalances = chainBalances[account.address as Hex];\n if (accountBalances) {\n for (const [tokenAddress, balance] of Object.entries(\n accountBalances,\n )) {\n // Find token in TokensController state\n const chainTokens = tokensState.allTokens[chainId as Hex];\n const accountTokens = chainTokens?.[account.address];\n const token = accountTokens?.find(\n (t) => t.address === tokenAddress,\n );\n if (!token) {\n continue;\n }\n\n const decimals = token.decimals || 18;\n const balanceInSmallestUnit = parseInt(balance as string, 16);\n const balanceInTokenUnits =\n balanceInSmallestUnit / Math.pow(10, decimals);\n\n // Get token rate in native currency from TokenRatesController\n const chainMarketData =\n tokenRatesState.marketData[chainId as Hex];\n const tokenMarketData = chainMarketData?.[tokenAddress as Hex];\n if (tokenMarketData?.price) {\n // Convert native currency price to USD using the appropriate native currency rate\n const nativeCurrency = tokenMarketData.currency;\n const nativeRate =\n currencyRateState.currencyRates[nativeCurrency];\n const nativeToUsdRate = nativeRate?.conversionRate || 1;\n const tokenPriceInUSD =\n tokenMarketData.price * nativeToUsdRate;\n const balanceInUSD = balanceInTokenUnits * tokenPriceInUSD;\n totalBalanceInUSD += balanceInUSD;\n }\n }\n }\n }\n } else {\n // Handle non-EVM account balances from MultichainBalancesController\n const accountBalances = multichainBalancesState.balances[account.id];\n if (accountBalances) {\n for (const [assetId, balanceData] of Object.entries(\n accountBalances,\n )) {\n const balanceAmount = parseFloat(balanceData.amount);\n\n // Get conversion rate for this asset\n const conversionRate =\n multichainRatesState.conversionRates[assetId as CaipAssetType];\n if (conversionRate) {\n const balanceInUSD =\n balanceAmount * parseFloat(conversionRate.rate);\n totalBalanceInUSD += balanceInUSD;\n }\n }\n }\n }\n }\n\n // Convert USD balance to user's selected currency\n const totalBalanceInUserCurrency = convertUsdToUserCurrency(\n totalBalanceInUSD,\n currencyRateState,\n );\n\n return {\n walletId,\n groupId,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Aggregated balance for an account group\n */\nexport type AccountGroupBalance = {\n walletId: string;\n groupId: string;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Aggregated balance for a wallet (all groups)\n */\nexport type WalletBalance = {\n walletId: string;\n groups: Record<string, AccountGroupBalance>;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Aggregated balance for all wallets\n */\nexport type AllWalletsBalance = {\n wallets: Record<string, WalletBalance>;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Selector to get aggregated balances for all account groups in a wallet.\n * Returns total balance in user's selected currency, aggregating all tokens across all groups in the wallet.\n *\n * @param walletId - The wallet ID (entropy source)\n * @returns Aggregated balance for all groups in the wallet\n */\nexport const selectBalanceByWallet = (walletId: EntropySourceId) =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): WalletBalance => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const wallet = (accountTreeState.accountTree.wallets as any)[walletId];\n if (!wallet) {\n return {\n walletId,\n groups: {},\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n };\n }\n\n const groupBalances: Record<string, AccountGroupBalance> = {};\n let totalBalanceInUserCurrency = 0;\n\n const groups = Object.keys(wallet.groups || {}) as string[];\n\n for (const groupId of groups) {\n const groupBalance = selectBalanceByAccountGroup(groupId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n\n groupBalances[groupId] = groupBalance;\n totalBalanceInUserCurrency += groupBalance.totalBalanceInUserCurrency;\n }\n\n return {\n walletId,\n groups: groupBalances,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Selector to get aggregated balances for all wallets and their account groups.\n * Returns total balance in user's selected currency, aggregating all tokens across all wallets.\n *\n * @returns Aggregated balance for all wallets\n */\nexport const selectBalanceForAllWallets = () =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AllWalletsBalance => {\n const walletBalances: Record<string, WalletBalance> = {};\n let totalBalanceInUserCurrency = 0;\n\n const walletIds = Object.keys(\n accountTreeState.accountTree.wallets,\n ) as string[];\n\n for (const walletId of walletIds) {\n const walletBalance = selectBalanceByWallet(walletId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n\n walletBalances[walletId] = walletBalance;\n totalBalanceInUserCurrency += walletBalance.totalBalanceInUserCurrency;\n }\n\n return {\n wallets: walletBalances,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Selector to get aggregated balances for the currently selected account group.\n * Returns total balance in user's selected currency, aggregating all tokens in the selected group.\n *\n * @returns Aggregated balance for the currently selected group\n */\nexport const selectBalanceForSelectedAccountGroup = () =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AccountGroupBalance | null => {\n const selectedGroupId = accountTreeState.accountTree.selectedAccountGroup;\n\n if (!selectedGroupId) {\n return null;\n }\n\n // Validate group ID format\n const parts = selectedGroupId.split('/');\n if (parts.length !== 2) {\n return null;\n }\n\n return selectBalanceByAccountGroup(selectedGroupId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n },\n );\n\n/**\n * Collection of balance-related selectors for assets controllers\n */\nexport const balanceSelectors = {\n selectBalanceByAccountGroup,\n selectBalanceByWallet,\n selectBalanceForAllWallets,\n selectBalanceForSelectedAccountGroup,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"balanceSelectors.cjs","sourceRoot":"","sources":["../../src/selectors/balanceSelectors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountTreeControllerState } from '@metamask/account-tree-controller';\nimport type { AccountWalletObject } from '@metamask/account-tree-controller';\nimport type { AccountGroupObject } from '@metamask/account-tree-controller';\nimport type { AccountsControllerState } from '@metamask/accounts-controller';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { Hex } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\nimport { createSelector } from 'reselect';\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\n/**\n * Root state type for all controllers used in selectors\n */\nexport type RootState = {\n TokenBalancesController: TokenBalancesControllerState;\n CurrencyRateController: CurrencyRateState;\n TokenRatesController: TokenRatesControllerState;\n MultichainAssetsRatesController: MultichainAssetsRatesControllerState;\n MultichainBalancesController: MultichainBalancesControllerState;\n TokensController: TokensControllerState;\n AccountsController: AccountsControllerState;\n AccountTreeController: AccountTreeControllerState;\n};\n\n/**\n * Helper function to get internal accounts for a specific group.\n * Uses AccountTreeController state to find accounts.\n *\n * @param accountTreeState - AccountTreeController state\n * @param accountsState - AccountsController state\n * @param groupId - The account group ID (format: \"walletId/groupIndex\")\n * @returns Array of internal accounts in the group\n */\nconst getInternalAccountsForGroup = (\n accountTreeState: AccountTreeControllerState,\n accountsState: AccountsControllerState,\n groupId: string,\n) => {\n // Extract walletId from groupId (format: \"walletId/groupIndex\")\n const walletId = groupId.split('/')[0] as EntropySourceId;\n\n const wallet = (\n accountTreeState.accountTree.wallets as Record<string, AccountWalletObject>\n )[walletId];\n if (!wallet) {\n return [];\n }\n\n const group = (wallet.groups as Record<string, AccountGroupObject>)[groupId];\n if (!group) {\n return [];\n }\n\n // Map account IDs to actual account objects\n return group.accounts\n .map(\n (accountId: string) => accountsState.internalAccounts.accounts[accountId],\n )\n .filter(Boolean);\n};\n\n/**\n * Selector to get aggregated balances for a specific account group.\n * Returns total balance in user's selected currency, aggregating all tokens across accounts in the group.\n *\n * @param groupId - The account group ID (format: \"walletId/groupIndex\", e.g., \"entropy:entropy-source-1/0\")\n * @returns Aggregated balance for the account group\n */\nexport const selectBalanceByAccountGroup = (groupId: string) =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AccountGroupBalance => {\n // Extract walletId from groupId\n const walletId = groupId.split('/')[0] as EntropySourceId;\n\n const accounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsState,\n groupId,\n );\n\n if (accounts.length === 0) {\n return {\n walletId,\n groupId,\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n };\n }\n\n let totalBalanceInUserCurrency = 0;\n\n // Process each account's balances\n for (const account of accounts) {\n const isEvmAccount = isEvmAccountType(account.type);\n\n if (isEvmAccount) {\n // Handle EVM account balances from TokenBalancesController\n // Structure: tokenBalances[chainId][accountAddress][tokenAddress] = balance\n for (const [chainId, chainBalances] of Object.entries(\n tokenBalancesState.tokenBalances,\n )) {\n const accountBalances = chainBalances[account.address as Hex];\n if (accountBalances) {\n for (const [tokenAddress, balance] of Object.entries(\n accountBalances,\n )) {\n // Find token in TokensController state\n const chainTokens = tokensState.allTokens[chainId as Hex];\n const accountTokens = chainTokens?.[account.address];\n const token = accountTokens?.find(\n (t) => t.address === tokenAddress,\n );\n if (!token) {\n continue;\n }\n\n const decimals = token.decimals || 18;\n const balanceInSmallestUnit = parseInt(balance as string, 16);\n\n // Skip invalid balance values to prevent NaN propagation\n if (Number.isNaN(balanceInSmallestUnit)) {\n continue;\n }\n\n const balanceInTokenUnits =\n balanceInSmallestUnit / Math.pow(10, decimals);\n\n // Get token rate in native currency from TokenRatesController\n const chainMarketData =\n tokenRatesState.marketData[chainId as Hex];\n const tokenMarketData = chainMarketData?.[tokenAddress as Hex];\n if (tokenMarketData?.price) {\n // Convert token price to user currency using native currency conversion rate\n const nativeCurrency = tokenMarketData.currency;\n const nativeToUserRate =\n currencyRateState.currencyRates[nativeCurrency]\n ?.conversionRate;\n\n if (nativeToUserRate) {\n // Convert token price to user currency: tokenPrice * nativeToUserRate\n const tokenPriceInUserCurrency =\n tokenMarketData.price * nativeToUserRate;\n const balanceInUserCurrency =\n balanceInTokenUnits * tokenPriceInUserCurrency;\n totalBalanceInUserCurrency += balanceInUserCurrency;\n }\n }\n }\n }\n }\n } else {\n // Handle non-EVM account balances from MultichainBalancesController\n const accountBalances = multichainBalancesState.balances[account.id];\n if (accountBalances) {\n for (const [assetId, balanceData] of Object.entries(\n accountBalances,\n )) {\n const balanceAmount = parseFloat(balanceData.amount);\n\n // Skip invalid balance values to prevent NaN propagation\n if (Number.isNaN(balanceAmount)) {\n continue;\n }\n\n // Get conversion rate for this asset (already in user currency)\n const conversionRate =\n multichainRatesState.conversionRates[assetId as CaipAssetType];\n if (conversionRate) {\n const conversionRateValue = parseFloat(conversionRate.rate);\n\n // Skip invalid conversion rate values to prevent NaN propagation\n if (Number.isNaN(conversionRateValue)) {\n continue;\n }\n\n // MultichainAssetsRatesController already provides rates in user currency\n const balanceInUserCurrency =\n balanceAmount * conversionRateValue;\n totalBalanceInUserCurrency += balanceInUserCurrency;\n }\n }\n }\n }\n }\n\n return {\n walletId,\n groupId,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Aggregated balance for an account group\n */\nexport type AccountGroupBalance = {\n walletId: string;\n groupId: string;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Aggregated balance for a wallet (all groups)\n */\nexport type WalletBalance = {\n walletId: string;\n groups: Record<string, AccountGroupBalance>;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Aggregated balance for all wallets\n */\nexport type AllWalletsBalance = {\n wallets: Record<string, WalletBalance>;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Selector to get aggregated balances for all account groups in a wallet.\n * Returns total balance in user's selected currency, aggregating all tokens across all groups in the wallet.\n *\n * @param walletId - The wallet ID (entropy source)\n * @returns Aggregated balance for all groups in the wallet\n */\nexport const selectBalanceByWallet = (walletId: EntropySourceId) =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): WalletBalance => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const wallet = (accountTreeState.accountTree.wallets as any)[walletId];\n if (!wallet) {\n return {\n walletId,\n groups: {},\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n };\n }\n\n const groupBalances: Record<string, AccountGroupBalance> = {};\n let totalBalanceInUserCurrency = 0;\n\n const groups = Object.keys(wallet.groups || {}) as string[];\n\n for (const groupId of groups) {\n const groupBalance = selectBalanceByAccountGroup(groupId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n\n groupBalances[groupId] = groupBalance;\n totalBalanceInUserCurrency += groupBalance.totalBalanceInUserCurrency;\n }\n\n return {\n walletId,\n groups: groupBalances,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Selector to get aggregated balances for all wallets and their account groups.\n * Returns total balance in user's selected currency, aggregating all tokens across all wallets.\n *\n * @returns Aggregated balance for all wallets\n */\nexport const selectBalanceForAllWallets = () =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AllWalletsBalance => {\n const walletBalances: Record<string, WalletBalance> = {};\n let totalBalanceInUserCurrency = 0;\n\n const walletIds = Object.keys(\n accountTreeState.accountTree.wallets,\n ) as string[];\n\n for (const walletId of walletIds) {\n const walletBalance = selectBalanceByWallet(walletId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n\n walletBalances[walletId] = walletBalance;\n totalBalanceInUserCurrency += walletBalance.totalBalanceInUserCurrency;\n }\n\n return {\n wallets: walletBalances,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Selector to get aggregated balances for the currently selected account group.\n * Returns total balance in user's selected currency, aggregating all tokens in the selected group.\n *\n * @returns Aggregated balance for the currently selected group\n */\nexport const selectBalanceForSelectedAccountGroup = () =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AccountGroupBalance | null => {\n const selectedGroupId = accountTreeState.accountTree.selectedAccountGroup;\n\n if (!selectedGroupId) {\n return null;\n }\n\n // Validate group ID format\n const parts = selectedGroupId.split('/');\n if (parts.length !== 2) {\n return null;\n }\n\n return selectBalanceByAccountGroup(selectedGroupId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n },\n );\n\n/**\n * Collection of balance-related selectors for assets controllers\n */\nexport const balanceSelectors = {\n selectBalanceByAccountGroup,\n selectBalanceByWallet,\n selectBalanceForAllWallets,\n selectBalanceForSelectedAccountGroup,\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balanceSelectors.d.cts","sourceRoot":"","sources":["../../src/selectors/balanceSelectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,0CAA0C;AAGpF,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAsC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAM7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,sCAAkC;AACnE,OAAO,KAAK,EAAE,oCAAoC,EAAE,qDAA2C;AAC/F,OAAO,KAAK,EAAE,iCAAiC,EAAE,kDAAwC;AACzF,OAAO,KAAK,EAAE,4BAA4B,EAAE,uCAAmC;AAC/E,OAAO,KAAK,EAAE,yBAAyB,EAAE,oCAAgC;AACzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,gCAA4B;AAEjE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,uBAAuB,EAAE,4BAA4B,CAAC;IACtD,sBAAsB,EAAE,iBAAiB,CAAC;IAC1C,oBAAoB,EAAE,yBAAyB,CAAC;IAChD,+BAA+B,EAAE,oCAAoC,CAAC;IACtE,4BAA4B,EAAE,iCAAiC,CAAC;IAChE,gBAAgB,EAAE,qBAAqB,CAAC;IACxC,kBAAkB,EAAE,uBAAuB,CAAC;IAC5C,qBAAqB,EAAE,0BAA0B,CAAC;CACnD,CAAC;
|
|
1
|
+
{"version":3,"file":"balanceSelectors.d.cts","sourceRoot":"","sources":["../../src/selectors/balanceSelectors.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balanceSelectors.d.mts","sourceRoot":"","sources":["../../src/selectors/balanceSelectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,0CAA0C;AAGpF,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAsC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAM7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,sCAAkC;AACnE,OAAO,KAAK,EAAE,oCAAoC,EAAE,qDAA2C;AAC/F,OAAO,KAAK,EAAE,iCAAiC,EAAE,kDAAwC;AACzF,OAAO,KAAK,EAAE,4BAA4B,EAAE,uCAAmC;AAC/E,OAAO,KAAK,EAAE,yBAAyB,EAAE,oCAAgC;AACzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,gCAA4B;AAEjE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,uBAAuB,EAAE,4BAA4B,CAAC;IACtD,sBAAsB,EAAE,iBAAiB,CAAC;IAC1C,oBAAoB,EAAE,yBAAyB,CAAC;IAChD,+BAA+B,EAAE,oCAAoC,CAAC;IACtE,4BAA4B,EAAE,iCAAiC,CAAC;IAChE,gBAAgB,EAAE,qBAAqB,CAAC;IACxC,kBAAkB,EAAE,uBAAuB,CAAC;IAC5C,qBAAqB,EAAE,0BAA0B,CAAC;CACnD,CAAC;
|
|
1
|
+
{"version":3,"file":"balanceSelectors.d.mts","sourceRoot":"","sources":["../../src/selectors/balanceSelectors.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,28 +25,6 @@ const getInternalAccountsForGroup = (accountTreeState, accountsState, groupId) =
|
|
|
25
25
|
.map((accountId) => accountsState.internalAccounts.accounts[accountId])
|
|
26
26
|
.filter(Boolean);
|
|
27
27
|
};
|
|
28
|
-
/**
|
|
29
|
-
* Helper function to convert USD amount to user's selected currency
|
|
30
|
-
*
|
|
31
|
-
* @param usdAmount - Amount in USD
|
|
32
|
-
* @param currencyRateState - CurrencyRateController state
|
|
33
|
-
* @returns Amount converted to user's selected currency
|
|
34
|
-
*/
|
|
35
|
-
const convertUsdToUserCurrency = (usdAmount, currencyRateState) => {
|
|
36
|
-
// If user currency is USD, no conversion needed
|
|
37
|
-
if (currencyRateState.currentCurrency.toLowerCase() === 'usd') {
|
|
38
|
-
return usdAmount;
|
|
39
|
-
}
|
|
40
|
-
// Get USD conversion rate for the user's currency
|
|
41
|
-
// We need to find a currency that has usdConversionRate set
|
|
42
|
-
const currencyWithUsdRate = Object.values(currencyRateState.currencyRates).find((rate) => rate.usdConversionRate !== null);
|
|
43
|
-
if (!currencyWithUsdRate?.usdConversionRate) {
|
|
44
|
-
// If no USD conversion rate is available, return USD amount as fallback
|
|
45
|
-
return usdAmount;
|
|
46
|
-
}
|
|
47
|
-
// Convert USD to user currency using the USD conversion rate
|
|
48
|
-
return usdAmount * currencyWithUsdRate.usdConversionRate;
|
|
49
|
-
};
|
|
50
28
|
/**
|
|
51
29
|
* Selector to get aggregated balances for a specific account group.
|
|
52
30
|
* Returns total balance in user's selected currency, aggregating all tokens across accounts in the group.
|
|
@@ -75,7 +53,7 @@ export const selectBalanceByAccountGroup = (groupId) => createSelector([
|
|
|
75
53
|
userCurrency: currencyRateState.currentCurrency,
|
|
76
54
|
};
|
|
77
55
|
}
|
|
78
|
-
let
|
|
56
|
+
let totalBalanceInUserCurrency = 0;
|
|
79
57
|
// Process each account's balances
|
|
80
58
|
for (const account of accounts) {
|
|
81
59
|
const isEvmAccount = isEvmAccountType(account.type);
|
|
@@ -95,18 +73,25 @@ export const selectBalanceByAccountGroup = (groupId) => createSelector([
|
|
|
95
73
|
}
|
|
96
74
|
const decimals = token.decimals || 18;
|
|
97
75
|
const balanceInSmallestUnit = parseInt(balance, 16);
|
|
76
|
+
// Skip invalid balance values to prevent NaN propagation
|
|
77
|
+
if (Number.isNaN(balanceInSmallestUnit)) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
98
80
|
const balanceInTokenUnits = balanceInSmallestUnit / Math.pow(10, decimals);
|
|
99
81
|
// Get token rate in native currency from TokenRatesController
|
|
100
82
|
const chainMarketData = tokenRatesState.marketData[chainId];
|
|
101
83
|
const tokenMarketData = chainMarketData?.[tokenAddress];
|
|
102
84
|
if (tokenMarketData?.price) {
|
|
103
|
-
// Convert
|
|
85
|
+
// Convert token price to user currency using native currency conversion rate
|
|
104
86
|
const nativeCurrency = tokenMarketData.currency;
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
87
|
+
const nativeToUserRate = currencyRateState.currencyRates[nativeCurrency]
|
|
88
|
+
?.conversionRate;
|
|
89
|
+
if (nativeToUserRate) {
|
|
90
|
+
// Convert token price to user currency: tokenPrice * nativeToUserRate
|
|
91
|
+
const tokenPriceInUserCurrency = tokenMarketData.price * nativeToUserRate;
|
|
92
|
+
const balanceInUserCurrency = balanceInTokenUnits * tokenPriceInUserCurrency;
|
|
93
|
+
totalBalanceInUserCurrency += balanceInUserCurrency;
|
|
94
|
+
}
|
|
110
95
|
}
|
|
111
96
|
}
|
|
112
97
|
}
|
|
@@ -118,18 +103,26 @@ export const selectBalanceByAccountGroup = (groupId) => createSelector([
|
|
|
118
103
|
if (accountBalances) {
|
|
119
104
|
for (const [assetId, balanceData] of Object.entries(accountBalances)) {
|
|
120
105
|
const balanceAmount = parseFloat(balanceData.amount);
|
|
121
|
-
//
|
|
106
|
+
// Skip invalid balance values to prevent NaN propagation
|
|
107
|
+
if (Number.isNaN(balanceAmount)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
// Get conversion rate for this asset (already in user currency)
|
|
122
111
|
const conversionRate = multichainRatesState.conversionRates[assetId];
|
|
123
112
|
if (conversionRate) {
|
|
124
|
-
const
|
|
125
|
-
|
|
113
|
+
const conversionRateValue = parseFloat(conversionRate.rate);
|
|
114
|
+
// Skip invalid conversion rate values to prevent NaN propagation
|
|
115
|
+
if (Number.isNaN(conversionRateValue)) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// MultichainAssetsRatesController already provides rates in user currency
|
|
119
|
+
const balanceInUserCurrency = balanceAmount * conversionRateValue;
|
|
120
|
+
totalBalanceInUserCurrency += balanceInUserCurrency;
|
|
126
121
|
}
|
|
127
122
|
}
|
|
128
123
|
}
|
|
129
124
|
}
|
|
130
125
|
}
|
|
131
|
-
// Convert USD balance to user's selected currency
|
|
132
|
-
const totalBalanceInUserCurrency = convertUsdToUserCurrency(totalBalanceInUSD, currencyRateState);
|
|
133
126
|
return {
|
|
134
127
|
walletId,
|
|
135
128
|
groupId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balanceSelectors.mjs","sourceRoot":"","sources":["../../src/selectors/balanceSelectors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountTreeControllerState } from '@metamask/account-tree-controller';\nimport type { AccountWalletObject } from '@metamask/account-tree-controller';\nimport type { AccountGroupObject } from '@metamask/account-tree-controller';\nimport type { AccountsControllerState } from '@metamask/accounts-controller';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { Hex } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\nimport { createSelector } from 'reselect';\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\n/**\n * Root state type for all controllers used in selectors\n */\nexport type RootState = {\n TokenBalancesController: TokenBalancesControllerState;\n CurrencyRateController: CurrencyRateState;\n TokenRatesController: TokenRatesControllerState;\n MultichainAssetsRatesController: MultichainAssetsRatesControllerState;\n MultichainBalancesController: MultichainBalancesControllerState;\n TokensController: TokensControllerState;\n AccountsController: AccountsControllerState;\n AccountTreeController: AccountTreeControllerState;\n};\n\n/**\n * Helper function to get internal accounts for a specific group.\n * Uses AccountTreeController state to find accounts.\n *\n * @param accountTreeState - AccountTreeController state\n * @param accountsState - AccountsController state\n * @param groupId - The account group ID (format: \"walletId/groupIndex\")\n * @returns Array of internal accounts in the group\n */\nconst getInternalAccountsForGroup = (\n accountTreeState: AccountTreeControllerState,\n accountsState: AccountsControllerState,\n groupId: string,\n) => {\n // Extract walletId from groupId (format: \"walletId/groupIndex\")\n const walletId = groupId.split('/')[0] as EntropySourceId;\n\n const wallet = (\n accountTreeState.accountTree.wallets as Record<string, AccountWalletObject>\n )[walletId];\n if (!wallet) {\n return [];\n }\n\n const group = (wallet.groups as Record<string, AccountGroupObject>)[groupId];\n if (!group) {\n return [];\n }\n\n // Map account IDs to actual account objects\n return group.accounts\n .map(\n (accountId: string) => accountsState.internalAccounts.accounts[accountId],\n )\n .filter(Boolean);\n};\n\n/**\n * Helper function to convert USD amount to user's selected currency\n *\n * @param usdAmount - Amount in USD\n * @param currencyRateState - CurrencyRateController state\n * @returns Amount converted to user's selected currency\n */\nconst convertUsdToUserCurrency = (\n usdAmount: number,\n currencyRateState: CurrencyRateState,\n): number => {\n // If user currency is USD, no conversion needed\n if (currencyRateState.currentCurrency.toLowerCase() === 'usd') {\n return usdAmount;\n }\n\n // Get USD conversion rate for the user's currency\n // We need to find a currency that has usdConversionRate set\n const currencyWithUsdRate = Object.values(\n currencyRateState.currencyRates,\n ).find((rate) => rate.usdConversionRate !== null);\n\n if (!currencyWithUsdRate?.usdConversionRate) {\n // If no USD conversion rate is available, return USD amount as fallback\n return usdAmount;\n }\n\n // Convert USD to user currency using the USD conversion rate\n return usdAmount * currencyWithUsdRate.usdConversionRate;\n};\n\n/**\n * Selector to get aggregated balances for a specific account group.\n * Returns total balance in user's selected currency, aggregating all tokens across accounts in the group.\n *\n * @param groupId - The account group ID (format: \"walletId/groupIndex\", e.g., \"entropy:entropy-source-1/0\")\n * @returns Aggregated balance for the account group\n */\nexport const selectBalanceByAccountGroup = (groupId: string) =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AccountGroupBalance => {\n // Extract walletId from groupId\n const walletId = groupId.split('/')[0] as EntropySourceId;\n\n const accounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsState,\n groupId,\n );\n\n if (accounts.length === 0) {\n return {\n walletId,\n groupId,\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n };\n }\n\n let totalBalanceInUSD = 0;\n\n // Process each account's balances\n for (const account of accounts) {\n const isEvmAccount = isEvmAccountType(account.type);\n\n if (isEvmAccount) {\n // Handle EVM account balances from TokenBalancesController\n // Structure: tokenBalances[chainId][accountAddress][tokenAddress] = balance\n for (const [chainId, chainBalances] of Object.entries(\n tokenBalancesState.tokenBalances,\n )) {\n const accountBalances = chainBalances[account.address as Hex];\n if (accountBalances) {\n for (const [tokenAddress, balance] of Object.entries(\n accountBalances,\n )) {\n // Find token in TokensController state\n const chainTokens = tokensState.allTokens[chainId as Hex];\n const accountTokens = chainTokens?.[account.address];\n const token = accountTokens?.find(\n (t) => t.address === tokenAddress,\n );\n if (!token) {\n continue;\n }\n\n const decimals = token.decimals || 18;\n const balanceInSmallestUnit = parseInt(balance as string, 16);\n const balanceInTokenUnits =\n balanceInSmallestUnit / Math.pow(10, decimals);\n\n // Get token rate in native currency from TokenRatesController\n const chainMarketData =\n tokenRatesState.marketData[chainId as Hex];\n const tokenMarketData = chainMarketData?.[tokenAddress as Hex];\n if (tokenMarketData?.price) {\n // Convert native currency price to USD using the appropriate native currency rate\n const nativeCurrency = tokenMarketData.currency;\n const nativeRate =\n currencyRateState.currencyRates[nativeCurrency];\n const nativeToUsdRate = nativeRate?.conversionRate || 1;\n const tokenPriceInUSD =\n tokenMarketData.price * nativeToUsdRate;\n const balanceInUSD = balanceInTokenUnits * tokenPriceInUSD;\n totalBalanceInUSD += balanceInUSD;\n }\n }\n }\n }\n } else {\n // Handle non-EVM account balances from MultichainBalancesController\n const accountBalances = multichainBalancesState.balances[account.id];\n if (accountBalances) {\n for (const [assetId, balanceData] of Object.entries(\n accountBalances,\n )) {\n const balanceAmount = parseFloat(balanceData.amount);\n\n // Get conversion rate for this asset\n const conversionRate =\n multichainRatesState.conversionRates[assetId as CaipAssetType];\n if (conversionRate) {\n const balanceInUSD =\n balanceAmount * parseFloat(conversionRate.rate);\n totalBalanceInUSD += balanceInUSD;\n }\n }\n }\n }\n }\n\n // Convert USD balance to user's selected currency\n const totalBalanceInUserCurrency = convertUsdToUserCurrency(\n totalBalanceInUSD,\n currencyRateState,\n );\n\n return {\n walletId,\n groupId,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Aggregated balance for an account group\n */\nexport type AccountGroupBalance = {\n walletId: string;\n groupId: string;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Aggregated balance for a wallet (all groups)\n */\nexport type WalletBalance = {\n walletId: string;\n groups: Record<string, AccountGroupBalance>;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Aggregated balance for all wallets\n */\nexport type AllWalletsBalance = {\n wallets: Record<string, WalletBalance>;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Selector to get aggregated balances for all account groups in a wallet.\n * Returns total balance in user's selected currency, aggregating all tokens across all groups in the wallet.\n *\n * @param walletId - The wallet ID (entropy source)\n * @returns Aggregated balance for all groups in the wallet\n */\nexport const selectBalanceByWallet = (walletId: EntropySourceId) =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): WalletBalance => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const wallet = (accountTreeState.accountTree.wallets as any)[walletId];\n if (!wallet) {\n return {\n walletId,\n groups: {},\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n };\n }\n\n const groupBalances: Record<string, AccountGroupBalance> = {};\n let totalBalanceInUserCurrency = 0;\n\n const groups = Object.keys(wallet.groups || {}) as string[];\n\n for (const groupId of groups) {\n const groupBalance = selectBalanceByAccountGroup(groupId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n\n groupBalances[groupId] = groupBalance;\n totalBalanceInUserCurrency += groupBalance.totalBalanceInUserCurrency;\n }\n\n return {\n walletId,\n groups: groupBalances,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Selector to get aggregated balances for all wallets and their account groups.\n * Returns total balance in user's selected currency, aggregating all tokens across all wallets.\n *\n * @returns Aggregated balance for all wallets\n */\nexport const selectBalanceForAllWallets = () =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AllWalletsBalance => {\n const walletBalances: Record<string, WalletBalance> = {};\n let totalBalanceInUserCurrency = 0;\n\n const walletIds = Object.keys(\n accountTreeState.accountTree.wallets,\n ) as string[];\n\n for (const walletId of walletIds) {\n const walletBalance = selectBalanceByWallet(walletId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n\n walletBalances[walletId] = walletBalance;\n totalBalanceInUserCurrency += walletBalance.totalBalanceInUserCurrency;\n }\n\n return {\n wallets: walletBalances,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Selector to get aggregated balances for the currently selected account group.\n * Returns total balance in user's selected currency, aggregating all tokens in the selected group.\n *\n * @returns Aggregated balance for the currently selected group\n */\nexport const selectBalanceForSelectedAccountGroup = () =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AccountGroupBalance | null => {\n const selectedGroupId = accountTreeState.accountTree.selectedAccountGroup;\n\n if (!selectedGroupId) {\n return null;\n }\n\n // Validate group ID format\n const parts = selectedGroupId.split('/');\n if (parts.length !== 2) {\n return null;\n }\n\n return selectBalanceByAccountGroup(selectedGroupId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n },\n );\n\n/**\n * Collection of balance-related selectors for assets controllers\n */\nexport const balanceSelectors = {\n selectBalanceByAccountGroup,\n selectBalanceByWallet,\n selectBalanceForAllWallets,\n selectBalanceForSelectedAccountGroup,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"balanceSelectors.mjs","sourceRoot":"","sources":["../../src/selectors/balanceSelectors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountTreeControllerState } from '@metamask/account-tree-controller';\nimport type { AccountWalletObject } from '@metamask/account-tree-controller';\nimport type { AccountGroupObject } from '@metamask/account-tree-controller';\nimport type { AccountsControllerState } from '@metamask/accounts-controller';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { Hex } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\nimport { createSelector } from 'reselect';\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\n/**\n * Root state type for all controllers used in selectors\n */\nexport type RootState = {\n TokenBalancesController: TokenBalancesControllerState;\n CurrencyRateController: CurrencyRateState;\n TokenRatesController: TokenRatesControllerState;\n MultichainAssetsRatesController: MultichainAssetsRatesControllerState;\n MultichainBalancesController: MultichainBalancesControllerState;\n TokensController: TokensControllerState;\n AccountsController: AccountsControllerState;\n AccountTreeController: AccountTreeControllerState;\n};\n\n/**\n * Helper function to get internal accounts for a specific group.\n * Uses AccountTreeController state to find accounts.\n *\n * @param accountTreeState - AccountTreeController state\n * @param accountsState - AccountsController state\n * @param groupId - The account group ID (format: \"walletId/groupIndex\")\n * @returns Array of internal accounts in the group\n */\nconst getInternalAccountsForGroup = (\n accountTreeState: AccountTreeControllerState,\n accountsState: AccountsControllerState,\n groupId: string,\n) => {\n // Extract walletId from groupId (format: \"walletId/groupIndex\")\n const walletId = groupId.split('/')[0] as EntropySourceId;\n\n const wallet = (\n accountTreeState.accountTree.wallets as Record<string, AccountWalletObject>\n )[walletId];\n if (!wallet) {\n return [];\n }\n\n const group = (wallet.groups as Record<string, AccountGroupObject>)[groupId];\n if (!group) {\n return [];\n }\n\n // Map account IDs to actual account objects\n return group.accounts\n .map(\n (accountId: string) => accountsState.internalAccounts.accounts[accountId],\n )\n .filter(Boolean);\n};\n\n/**\n * Selector to get aggregated balances for a specific account group.\n * Returns total balance in user's selected currency, aggregating all tokens across accounts in the group.\n *\n * @param groupId - The account group ID (format: \"walletId/groupIndex\", e.g., \"entropy:entropy-source-1/0\")\n * @returns Aggregated balance for the account group\n */\nexport const selectBalanceByAccountGroup = (groupId: string) =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AccountGroupBalance => {\n // Extract walletId from groupId\n const walletId = groupId.split('/')[0] as EntropySourceId;\n\n const accounts = getInternalAccountsForGroup(\n accountTreeState,\n accountsState,\n groupId,\n );\n\n if (accounts.length === 0) {\n return {\n walletId,\n groupId,\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n };\n }\n\n let totalBalanceInUserCurrency = 0;\n\n // Process each account's balances\n for (const account of accounts) {\n const isEvmAccount = isEvmAccountType(account.type);\n\n if (isEvmAccount) {\n // Handle EVM account balances from TokenBalancesController\n // Structure: tokenBalances[chainId][accountAddress][tokenAddress] = balance\n for (const [chainId, chainBalances] of Object.entries(\n tokenBalancesState.tokenBalances,\n )) {\n const accountBalances = chainBalances[account.address as Hex];\n if (accountBalances) {\n for (const [tokenAddress, balance] of Object.entries(\n accountBalances,\n )) {\n // Find token in TokensController state\n const chainTokens = tokensState.allTokens[chainId as Hex];\n const accountTokens = chainTokens?.[account.address];\n const token = accountTokens?.find(\n (t) => t.address === tokenAddress,\n );\n if (!token) {\n continue;\n }\n\n const decimals = token.decimals || 18;\n const balanceInSmallestUnit = parseInt(balance as string, 16);\n\n // Skip invalid balance values to prevent NaN propagation\n if (Number.isNaN(balanceInSmallestUnit)) {\n continue;\n }\n\n const balanceInTokenUnits =\n balanceInSmallestUnit / Math.pow(10, decimals);\n\n // Get token rate in native currency from TokenRatesController\n const chainMarketData =\n tokenRatesState.marketData[chainId as Hex];\n const tokenMarketData = chainMarketData?.[tokenAddress as Hex];\n if (tokenMarketData?.price) {\n // Convert token price to user currency using native currency conversion rate\n const nativeCurrency = tokenMarketData.currency;\n const nativeToUserRate =\n currencyRateState.currencyRates[nativeCurrency]\n ?.conversionRate;\n\n if (nativeToUserRate) {\n // Convert token price to user currency: tokenPrice * nativeToUserRate\n const tokenPriceInUserCurrency =\n tokenMarketData.price * nativeToUserRate;\n const balanceInUserCurrency =\n balanceInTokenUnits * tokenPriceInUserCurrency;\n totalBalanceInUserCurrency += balanceInUserCurrency;\n }\n }\n }\n }\n }\n } else {\n // Handle non-EVM account balances from MultichainBalancesController\n const accountBalances = multichainBalancesState.balances[account.id];\n if (accountBalances) {\n for (const [assetId, balanceData] of Object.entries(\n accountBalances,\n )) {\n const balanceAmount = parseFloat(balanceData.amount);\n\n // Skip invalid balance values to prevent NaN propagation\n if (Number.isNaN(balanceAmount)) {\n continue;\n }\n\n // Get conversion rate for this asset (already in user currency)\n const conversionRate =\n multichainRatesState.conversionRates[assetId as CaipAssetType];\n if (conversionRate) {\n const conversionRateValue = parseFloat(conversionRate.rate);\n\n // Skip invalid conversion rate values to prevent NaN propagation\n if (Number.isNaN(conversionRateValue)) {\n continue;\n }\n\n // MultichainAssetsRatesController already provides rates in user currency\n const balanceInUserCurrency =\n balanceAmount * conversionRateValue;\n totalBalanceInUserCurrency += balanceInUserCurrency;\n }\n }\n }\n }\n }\n\n return {\n walletId,\n groupId,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Aggregated balance for an account group\n */\nexport type AccountGroupBalance = {\n walletId: string;\n groupId: string;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Aggregated balance for a wallet (all groups)\n */\nexport type WalletBalance = {\n walletId: string;\n groups: Record<string, AccountGroupBalance>;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Aggregated balance for all wallets\n */\nexport type AllWalletsBalance = {\n wallets: Record<string, WalletBalance>;\n totalBalanceInUserCurrency: number; // not formatted\n userCurrency: string;\n};\n\n/**\n * Selector to get aggregated balances for all account groups in a wallet.\n * Returns total balance in user's selected currency, aggregating all tokens across all groups in the wallet.\n *\n * @param walletId - The wallet ID (entropy source)\n * @returns Aggregated balance for all groups in the wallet\n */\nexport const selectBalanceByWallet = (walletId: EntropySourceId) =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): WalletBalance => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const wallet = (accountTreeState.accountTree.wallets as any)[walletId];\n if (!wallet) {\n return {\n walletId,\n groups: {},\n totalBalanceInUserCurrency: 0,\n userCurrency: currencyRateState.currentCurrency,\n };\n }\n\n const groupBalances: Record<string, AccountGroupBalance> = {};\n let totalBalanceInUserCurrency = 0;\n\n const groups = Object.keys(wallet.groups || {}) as string[];\n\n for (const groupId of groups) {\n const groupBalance = selectBalanceByAccountGroup(groupId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n\n groupBalances[groupId] = groupBalance;\n totalBalanceInUserCurrency += groupBalance.totalBalanceInUserCurrency;\n }\n\n return {\n walletId,\n groups: groupBalances,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Selector to get aggregated balances for all wallets and their account groups.\n * Returns total balance in user's selected currency, aggregating all tokens across all wallets.\n *\n * @returns Aggregated balance for all wallets\n */\nexport const selectBalanceForAllWallets = () =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AllWalletsBalance => {\n const walletBalances: Record<string, WalletBalance> = {};\n let totalBalanceInUserCurrency = 0;\n\n const walletIds = Object.keys(\n accountTreeState.accountTree.wallets,\n ) as string[];\n\n for (const walletId of walletIds) {\n const walletBalance = selectBalanceByWallet(walletId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n\n walletBalances[walletId] = walletBalance;\n totalBalanceInUserCurrency += walletBalance.totalBalanceInUserCurrency;\n }\n\n return {\n wallets: walletBalances,\n totalBalanceInUserCurrency,\n userCurrency: currencyRateState.currentCurrency,\n };\n },\n );\n\n/**\n * Selector to get aggregated balances for the currently selected account group.\n * Returns total balance in user's selected currency, aggregating all tokens in the selected group.\n *\n * @returns Aggregated balance for the currently selected group\n */\nexport const selectBalanceForSelectedAccountGroup = () =>\n createSelector(\n [\n (state: RootState) => state.AccountTreeController,\n (state: RootState) => state.AccountsController,\n (state: RootState) => state.TokenBalancesController,\n (state: RootState) => state.TokenRatesController,\n (state: RootState) => state.MultichainAssetsRatesController,\n (state: RootState) => state.MultichainBalancesController,\n (state: RootState) => state.TokensController,\n (state: RootState) => state.CurrencyRateController,\n ],\n (\n accountTreeState,\n accountsState,\n tokenBalancesState,\n tokenRatesState,\n multichainRatesState,\n multichainBalancesState,\n tokensState,\n currencyRateState,\n ): AccountGroupBalance | null => {\n const selectedGroupId = accountTreeState.accountTree.selectedAccountGroup;\n\n if (!selectedGroupId) {\n return null;\n }\n\n // Validate group ID format\n const parts = selectedGroupId.split('/');\n if (parts.length !== 2) {\n return null;\n }\n\n return selectBalanceByAccountGroup(selectedGroupId)({\n AccountTreeController: accountTreeState,\n AccountsController: accountsState,\n TokenBalancesController: tokenBalancesState,\n TokenRatesController: tokenRatesState,\n MultichainAssetsRatesController: multichainRatesState,\n MultichainBalancesController: multichainBalancesState,\n TokensController: tokensState,\n CurrencyRateController: currencyRateState,\n });\n },\n );\n\n/**\n * Collection of balance-related selectors for assets controllers\n */\nexport const balanceSelectors = {\n selectBalanceByAccountGroup,\n selectBalanceByWallet,\n selectBalanceForAllWallets,\n selectBalanceForSelectedAccountGroup,\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/assets-controllers",
|
|
3
|
-
"version": "73.0.1-preview-
|
|
3
|
+
"version": "73.0.1-preview-e4e5ca5c",
|
|
4
4
|
"description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|