@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.
- package/CHANGELOG.md +43 -1
- package/dist/AccountTrackerController.cjs +51 -1
- package/dist/AccountTrackerController.cjs.map +1 -1
- package/dist/AccountTrackerController.d.cts +40 -1
- package/dist/AccountTrackerController.d.cts.map +1 -1
- package/dist/AccountTrackerController.d.mts +40 -1
- package/dist/AccountTrackerController.d.mts.map +1 -1
- package/dist/AccountTrackerController.mjs +51 -1
- package/dist/AccountTrackerController.mjs.map +1 -1
- package/dist/TokenBalancesController.cjs +278 -319
- package/dist/TokenBalancesController.cjs.map +1 -1
- package/dist/TokenBalancesController.d.cts +51 -93
- package/dist/TokenBalancesController.d.cts.map +1 -1
- package/dist/TokenBalancesController.d.mts +51 -93
- package/dist/TokenBalancesController.d.mts.map +1 -1
- package/dist/TokenBalancesController.mjs +277 -317
- package/dist/TokenBalancesController.mjs.map +1 -1
- package/dist/assetsUtil.cjs +13 -1
- package/dist/assetsUtil.cjs.map +1 -1
- package/dist/assetsUtil.d.cts +8 -0
- package/dist/assetsUtil.d.cts.map +1 -1
- package/dist/assetsUtil.d.mts +8 -0
- package/dist/assetsUtil.d.mts.map +1 -1
- package/dist/assetsUtil.mjs +12 -1
- package/dist/assetsUtil.mjs.map +1 -1
- package/dist/balances.cjs +447 -0
- package/dist/balances.cjs.map +1 -0
- package/dist/balances.d.cts +88 -0
- package/dist/balances.d.cts.map +1 -0
- package/dist/balances.d.mts +88 -0
- package/dist/balances.d.mts.map +1 -0
- package/dist/balances.mjs +441 -0
- package/dist/balances.mjs.map +1 -0
- package/dist/constants.cjs +13 -1
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +1 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +1 -0
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +12 -0
- package/dist/constants.mjs.map +1 -1
- package/dist/index.cjs +6 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +6 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs +286 -0
- package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs.map +1 -0
- package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts +30 -0
- package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts.map +1 -0
- package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts +30 -0
- package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts.map +1 -0
- package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs +286 -0
- package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs.map +1 -0
- package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs +35 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts +16 -0
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts +16 -0
- package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts.map +1 -1
- package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs +33 -0
- package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs.map +1 -1
- package/dist/multi-chain-accounts-service/types.cjs.map +1 -1
- package/dist/multi-chain-accounts-service/types.d.cts +8 -0
- package/dist/multi-chain-accounts-service/types.d.cts.map +1 -1
- package/dist/multi-chain-accounts-service/types.d.mts +8 -0
- package/dist/multi-chain-accounts-service/types.d.mts.map +1 -1
- package/dist/multi-chain-accounts-service/types.mjs.map +1 -1
- package/dist/multicall.cjs +457 -1
- package/dist/multicall.cjs.map +1 -1
- package/dist/multicall.d.cts +51 -0
- package/dist/multicall.d.cts.map +1 -1
- package/dist/multicall.d.mts +51 -0
- package/dist/multicall.d.mts.map +1 -1
- package/dist/multicall.mjs +457 -0
- package/dist/multicall.mjs.map +1 -1
- package/dist/rpc-service/rpc-balance-fetcher.cjs +184 -0
- package/dist/rpc-service/rpc-balance-fetcher.cjs.map +1 -0
- package/dist/rpc-service/rpc-balance-fetcher.d.cts +34 -0
- package/dist/rpc-service/rpc-balance-fetcher.d.cts.map +1 -0
- package/dist/rpc-service/rpc-balance-fetcher.d.mts +34 -0
- package/dist/rpc-service/rpc-balance-fetcher.d.mts.map +1 -0
- package/dist/rpc-service/rpc-balance-fetcher.mjs +184 -0
- package/dist/rpc-service/rpc-balance-fetcher.mjs.map +1 -0
- package/package.json +11 -11
- package/dist/selectors/balanceSelectors.cjs +0 -328
- package/dist/selectors/balanceSelectors.cjs.map +0 -1
- package/dist/selectors/balanceSelectors.d.cts +0 -1676
- package/dist/selectors/balanceSelectors.d.cts.map +0 -1
- package/dist/selectors/balanceSelectors.d.mts +0 -1676
- package/dist/selectors/balanceSelectors.d.mts.map +0 -1
- package/dist/selectors/balanceSelectors.mjs +0 -321
- 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"]}
|
package/dist/constants.cjs
CHANGED
|
@@ -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
|