@metamask/assets-controller 3.1.0 → 3.2.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 +39 -1
- package/dist/AssetsController-method-action-types.cjs +1 -1
- package/dist/AssetsController-method-action-types.cjs.map +1 -1
- package/dist/AssetsController-method-action-types.d.cts +1 -1
- package/dist/AssetsController-method-action-types.d.mts +1 -1
- package/dist/AssetsController-method-action-types.mjs +1 -1
- package/dist/AssetsController-method-action-types.mjs.map +1 -1
- package/dist/AssetsController.cjs +123 -22
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +123 -22
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/RpcDataSource.cjs +18 -22
- package/dist/data-sources/RpcDataSource.cjs.map +1 -1
- package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
- package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
- package/dist/data-sources/RpcDataSource.mjs +18 -22
- package/dist/data-sources/RpcDataSource.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.cjs +3 -6
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.mjs +1 -4
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/index.d.cts +1 -1
- package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/index.d.mts +1 -1
- package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs +87 -76
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts +20 -8
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts +20 -8
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.mjs +85 -74
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/index.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/index.d.cts +1 -1
- package/dist/data-sources/evm-rpc-services/types/index.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/index.d.mts +1 -1
- package/dist/data-sources/evm-rpc-services/types/index.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/index.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/services.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/services.d.cts +9 -17
- package/dist/data-sources/evm-rpc-services/types/services.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/services.d.mts +9 -17
- package/dist/data-sources/evm-rpc-services/types/services.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/types/services.mjs.map +1 -1
- package/dist/selectors/balance.cjs +26 -1
- package/dist/selectors/balance.cjs.map +1 -1
- package/dist/selectors/balance.d.cts +2 -1
- package/dist/selectors/balance.d.cts.map +1 -1
- package/dist/selectors/balance.d.mts +2 -1
- package/dist/selectors/balance.d.mts.map +1 -1
- package/dist/selectors/balance.mjs +26 -1
- package/dist/selectors/balance.mjs.map +1 -1
- package/dist/utils/constants.cjs +5 -0
- package/dist/utils/constants.cjs.map +1 -0
- package/dist/utils/constants.d.cts +2 -0
- package/dist/utils/constants.d.cts.map +1 -0
- package/dist/utils/constants.d.mts +2 -0
- package/dist/utils/constants.d.mts.map +1 -0
- package/dist/utils/constants.mjs +2 -0
- package/dist/utils/constants.mjs.map +1 -0
- package/package.json +14 -14
|
@@ -9,14 +9,20 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _BalanceFetcher_instances, _BalanceFetcher_multicallClient, _BalanceFetcher_messenger, _BalanceFetcher_config, _BalanceFetcher_onBalanceUpdate, _BalanceFetcher_processBalanceResponses, _BalanceFetcher_formatBalance;
|
|
12
|
+
var _BalanceFetcher_instances, _BalanceFetcher_multicallClient, _BalanceFetcher_messenger, _BalanceFetcher_config, _BalanceFetcher_onBalanceUpdate, _BalanceFetcher_getAssetsToFetch, _BalanceFetcher_fetchBalances, _BalanceFetcher_processBalanceResponses, _BalanceFetcher_formatBalance;
|
|
13
13
|
import { StaticIntervalPollingControllerOnly } from "@metamask/polling-controller";
|
|
14
|
+
import { parseCaipAssetType } from "@metamask/utils";
|
|
15
|
+
import { ZERO_ADDRESS } from "../../../utils/constants.mjs";
|
|
14
16
|
import { reduceInBatchesSerially } from "../utils/index.mjs";
|
|
15
17
|
const DEFAULT_BALANCE_INTERVAL = 30000; // 30 seconds
|
|
16
|
-
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
17
18
|
/**
|
|
18
19
|
* BalanceFetcher - Fetches token balances via multicall.
|
|
19
20
|
* Extends StaticIntervalPollingControllerOnly for built-in polling support.
|
|
21
|
+
*
|
|
22
|
+
* Callers provide CAIP-19 asset IDs; the fetcher extracts on-chain addresses
|
|
23
|
+
* (or uses the zero address for native assets) and maps multicall responses
|
|
24
|
+
* back to the original asset IDs. This ensures the returned balance entries
|
|
25
|
+
* always carry the correct identifier regardless of chain.
|
|
20
26
|
*/
|
|
21
27
|
export class BalanceFetcher extends StaticIntervalPollingControllerOnly() {
|
|
22
28
|
constructor(multicallClient, messenger, config) {
|
|
@@ -31,7 +37,6 @@ export class BalanceFetcher extends StaticIntervalPollingControllerOnly() {
|
|
|
31
37
|
__classPrivateFieldSet(this, _BalanceFetcher_config, {
|
|
32
38
|
defaultBatchSize: config?.defaultBatchSize ?? 300,
|
|
33
39
|
defaultTimeoutMs: config?.defaultTimeoutMs ?? 30000,
|
|
34
|
-
includeNativeByDefault: config?.includeNativeByDefault ?? true,
|
|
35
40
|
}, "f");
|
|
36
41
|
// Set the polling interval
|
|
37
42
|
this.setIntervalLength(config?.pollingInterval ?? DEFAULT_BALANCE_INTERVAL);
|
|
@@ -51,69 +56,36 @@ export class BalanceFetcher extends StaticIntervalPollingControllerOnly() {
|
|
|
51
56
|
* @param input - The polling input.
|
|
52
57
|
*/
|
|
53
58
|
async _executePoll(input) {
|
|
54
|
-
const result = await this.
|
|
59
|
+
const result = await __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_fetchBalances).call(this, input.chainId, input.accountId, input.accountAddress);
|
|
55
60
|
if (__classPrivateFieldGet(this, _BalanceFetcher_onBalanceUpdate, "f") && result.balances.length > 0) {
|
|
56
61
|
await __classPrivateFieldGet(this, _BalanceFetcher_onBalanceUpdate, "f").call(this, result);
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
for (const assetId of Object.keys(accountBalances)) {
|
|
73
|
-
// Only process ERC20 tokens on the current chain
|
|
74
|
-
if (assetId.startsWith(caipChainPrefix) && assetId.includes('/erc20:')) {
|
|
75
|
-
// Parse token address from CAIP-19: eip155:1/erc20:0x...
|
|
76
|
-
const tokenAddress = assetId.split('/erc20:')[1];
|
|
77
|
-
if (tokenAddress) {
|
|
78
|
-
const lowerAddress = tokenAddress.toLowerCase();
|
|
79
|
-
if (!tokenMap.has(lowerAddress)) {
|
|
80
|
-
tokenMap.set(lowerAddress, {
|
|
81
|
-
address: tokenAddress,
|
|
82
|
-
symbol: '',
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return Array.from(tokenMap.values());
|
|
89
|
-
}
|
|
90
|
-
async fetchBalances(chainId, accountId, accountAddress, options) {
|
|
91
|
-
const tokens = this.getTokensToFetch(chainId, accountId);
|
|
92
|
-
const tokenAddresses = tokens.map((token) => token.address);
|
|
93
|
-
return this.fetchBalancesForTokens(chainId, accountId, accountAddress, tokenAddresses, options, tokens);
|
|
94
|
-
}
|
|
95
|
-
async fetchBalancesForTokens(chainId, accountId, accountAddress, tokenAddresses, options, tokenInfos) {
|
|
96
|
-
const batchSize = options?.batchSize ?? __classPrivateFieldGet(this, _BalanceFetcher_config, "f").defaultBatchSize;
|
|
97
|
-
const includeNative = options?.includeNative ?? __classPrivateFieldGet(this, _BalanceFetcher_config, "f").includeNativeByDefault;
|
|
64
|
+
/**
|
|
65
|
+
* Fetch balances for the given assets via multicall.
|
|
66
|
+
*
|
|
67
|
+
* Each entry bundles a CAIP-19 asset ID with its on-chain address and
|
|
68
|
+
* optional decimals.
|
|
69
|
+
*
|
|
70
|
+
* @param chainId - Hex chain ID.
|
|
71
|
+
* @param accountId - Account UUID.
|
|
72
|
+
* @param accountAddress - On-chain address of the account.
|
|
73
|
+
* @param assets - Asset fetch entries to fetch balances for.
|
|
74
|
+
* @returns Balance fetch result.
|
|
75
|
+
*/
|
|
76
|
+
async fetchBalancesForAssets(chainId, accountId, accountAddress, assets) {
|
|
98
77
|
const timestamp = Date.now();
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
for (const info of tokenInfos) {
|
|
102
|
-
tokenInfoMap.set(info.address.toLowerCase(), info);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
78
|
+
// Build a single map keyed by lowercase address that holds all info
|
|
79
|
+
// needed to match multicall responses back to their original entries.
|
|
105
80
|
const balanceRequests = [];
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
balanceRequests.push({
|
|
114
|
-
tokenAddress,
|
|
115
|
-
accountAddress,
|
|
116
|
-
});
|
|
81
|
+
const entryByAddress = new Map();
|
|
82
|
+
for (const entry of assets) {
|
|
83
|
+
const lowerAddress = entry.address.toLowerCase();
|
|
84
|
+
if (entryByAddress.has(lowerAddress)) {
|
|
85
|
+
continue; // deduplicate
|
|
86
|
+
}
|
|
87
|
+
entryByAddress.set(lowerAddress, entry);
|
|
88
|
+
balanceRequests.push({ tokenAddress: entry.address, accountAddress });
|
|
117
89
|
}
|
|
118
90
|
if (balanceRequests.length === 0) {
|
|
119
91
|
return {
|
|
@@ -127,14 +99,14 @@ export class BalanceFetcher extends StaticIntervalPollingControllerOnly() {
|
|
|
127
99
|
}
|
|
128
100
|
const result = await reduceInBatchesSerially({
|
|
129
101
|
values: balanceRequests,
|
|
130
|
-
batchSize,
|
|
102
|
+
batchSize: __classPrivateFieldGet(this, _BalanceFetcher_config, "f").defaultBatchSize,
|
|
131
103
|
initialResult: {
|
|
132
104
|
balances: [],
|
|
133
105
|
failedAddresses: [],
|
|
134
106
|
},
|
|
135
107
|
eachBatch: async (workingResult, batch) => {
|
|
136
108
|
const responses = await __classPrivateFieldGet(this, _BalanceFetcher_multicallClient, "f").batchBalanceOf(chainId, batch);
|
|
137
|
-
return __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_processBalanceResponses).call(this, responses, workingResult, chainId, accountId, timestamp,
|
|
109
|
+
return __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_processBalanceResponses).call(this, responses, workingResult, chainId, accountId, timestamp, entryByAddress);
|
|
138
110
|
},
|
|
139
111
|
});
|
|
140
112
|
return {
|
|
@@ -146,37 +118,76 @@ export class BalanceFetcher extends StaticIntervalPollingControllerOnly() {
|
|
|
146
118
|
};
|
|
147
119
|
}
|
|
148
120
|
}
|
|
149
|
-
_BalanceFetcher_multicallClient = new WeakMap(), _BalanceFetcher_messenger = new WeakMap(), _BalanceFetcher_config = new WeakMap(), _BalanceFetcher_onBalanceUpdate = new WeakMap(), _BalanceFetcher_instances = new WeakSet(),
|
|
121
|
+
_BalanceFetcher_multicallClient = new WeakMap(), _BalanceFetcher_messenger = new WeakMap(), _BalanceFetcher_config = new WeakMap(), _BalanceFetcher_onBalanceUpdate = new WeakMap(), _BalanceFetcher_instances = new WeakSet(), _BalanceFetcher_getAssetsToFetch = function _BalanceFetcher_getAssetsToFetch(chainId, accountId) {
|
|
122
|
+
const state = __classPrivateFieldGet(this, _BalanceFetcher_messenger, "f").call('AssetsController:getState');
|
|
123
|
+
const accountBalances = state?.assetsBalance?.[accountId];
|
|
124
|
+
if (!accountBalances) {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
// Convert hex chainId to decimal for CAIP-2 matching
|
|
128
|
+
// This is safe because we are filtring with an accountId that is for evm balances only
|
|
129
|
+
const chainIdDecimal = parseInt(chainId, 16).toString();
|
|
130
|
+
const assetsToFetch = new Map();
|
|
131
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
132
|
+
const { chain: { reference: chainReference }, assetNamespace, assetReference, } = parseCaipAssetType(assetId);
|
|
133
|
+
if (chainReference === chainIdDecimal) {
|
|
134
|
+
const assetIdLowerCase = assetId.toLowerCase();
|
|
135
|
+
if (assetsToFetch.has(assetIdLowerCase)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const isNative = assetNamespace === 'slip44';
|
|
139
|
+
const tokenAddress = isNative
|
|
140
|
+
? ZERO_ADDRESS
|
|
141
|
+
: assetReference.toLowerCase();
|
|
142
|
+
assetsToFetch.set(assetIdLowerCase, {
|
|
143
|
+
assetId,
|
|
144
|
+
address: tokenAddress,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return Array.from(assetsToFetch.values());
|
|
149
|
+
}, _BalanceFetcher_fetchBalances =
|
|
150
|
+
/**
|
|
151
|
+
* Fetch balances for assets already tracked in state for the given
|
|
152
|
+
* account and chain.
|
|
153
|
+
*
|
|
154
|
+
* @param chainId - Hex chain ID.
|
|
155
|
+
* @param accountId - Account UUID.
|
|
156
|
+
* @param accountAddress - On-chain address of the account.
|
|
157
|
+
* @returns Balance fetch result.
|
|
158
|
+
*/
|
|
159
|
+
async function _BalanceFetcher_fetchBalances(chainId, accountId, accountAddress) {
|
|
160
|
+
const assets = __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_getAssetsToFetch).call(this, chainId, accountId);
|
|
161
|
+
return this.fetchBalancesForAssets(chainId, accountId, accountAddress, assets);
|
|
162
|
+
}, _BalanceFetcher_processBalanceResponses = function _BalanceFetcher_processBalanceResponses(responses, accumulator, chainId, accountId, timestamp, entryByAddress) {
|
|
150
163
|
const { balances, failedAddresses } = accumulator;
|
|
151
164
|
for (const response of responses) {
|
|
152
165
|
if (!response.success) {
|
|
153
166
|
failedAddresses.push(response.tokenAddress);
|
|
154
167
|
continue;
|
|
155
168
|
}
|
|
169
|
+
const lowerAddress = response.tokenAddress.toLowerCase();
|
|
170
|
+
const entry = entryByAddress.get(lowerAddress);
|
|
171
|
+
if (!entry) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
156
174
|
const balance = response.balance ?? '0';
|
|
157
|
-
const
|
|
158
|
-
const isNative = response.tokenAddress.toLowerCase() === ZERO_ADDRESS.toLowerCase();
|
|
159
|
-
const tokenInfo = tokenInfoMap.get(response.tokenAddress.toLowerCase());
|
|
160
|
-
// Native uses 18. ERC-20: format when decimals are known; otherwise pass raw
|
|
161
|
-
// `balance` through so RpcDataSource can resolve decimals (state → list → RPC).
|
|
175
|
+
const isNative = lowerAddress === ZERO_ADDRESS.toLowerCase();
|
|
162
176
|
let decimals;
|
|
163
177
|
let formattedBalance;
|
|
164
178
|
if (isNative) {
|
|
165
179
|
decimals = 18;
|
|
166
180
|
formattedBalance = __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_formatBalance).call(this, balance, decimals);
|
|
167
181
|
}
|
|
168
|
-
else if (
|
|
182
|
+
else if (entry.decimals === undefined) {
|
|
169
183
|
formattedBalance = balance;
|
|
170
184
|
}
|
|
171
185
|
else {
|
|
172
|
-
decimals =
|
|
186
|
+
decimals = entry.decimals;
|
|
173
187
|
formattedBalance = __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_formatBalance).call(this, balance, decimals);
|
|
174
188
|
}
|
|
175
|
-
const assetId = isNative
|
|
176
|
-
? `eip155:${chainIdDecimal}/slip44:60`
|
|
177
|
-
: `eip155:${chainIdDecimal}/erc20:${response.tokenAddress.toLowerCase()}`;
|
|
178
189
|
const balanceEntry = {
|
|
179
|
-
assetId,
|
|
190
|
+
assetId: entry.assetId,
|
|
180
191
|
accountId,
|
|
181
192
|
chainId,
|
|
182
193
|
balance,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BalanceFetcher.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/BalanceFetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { StaticIntervalPollingControllerOnly } from '@metamask/polling-controller';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport type { MulticallClient } from '../clients';\nimport type {\n AccountId,\n Address,\n AssetBalance,\n AssetsBalanceState,\n BalanceFetchOptions,\n BalanceFetchResult,\n BalanceOfRequest,\n BalanceOfResponse,\n ChainId,\n TokenFetchInfo,\n} from '../types';\nimport { reduceInBatchesSerially } from '../utils';\n\nconst DEFAULT_BALANCE_INTERVAL = 30_000; // 30 seconds\n\nconst ZERO_ADDRESS: Address =\n '0x0000000000000000000000000000000000000000' as Address;\n\n/**\n * Minimal messenger interface for BalanceFetcher.\n */\nexport type BalanceFetcherMessenger = {\n call: (action: 'AssetsController:getState') => AssetsBalanceState;\n};\n\nexport type BalanceFetcherConfig = {\n defaultBatchSize?: number;\n defaultTimeoutMs?: number;\n includeNativeByDefault?: boolean;\n /** Polling interval in ms (default: 30s) */\n pollingInterval?: number;\n};\n\n/**\n * Polling input for BalanceFetcher - identifies what to poll for.\n */\nexport type BalancePollingInput = {\n /** Chain ID (hex format) */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n};\n\n/**\n * Callback type for balance updates.\n */\nexport type OnBalanceUpdateCallback = (\n result: BalanceFetchResult,\n) => void | Promise<void>;\n\n/**\n * BalanceFetcher - Fetches token balances via multicall.\n * Extends StaticIntervalPollingControllerOnly for built-in polling support.\n */\nexport class BalanceFetcher extends StaticIntervalPollingControllerOnly<BalancePollingInput>() {\n readonly #multicallClient: MulticallClient;\n\n readonly #messenger: BalanceFetcherMessenger;\n\n readonly #config: Required<Omit<BalanceFetcherConfig, 'pollingInterval'>>;\n\n #onBalanceUpdate: OnBalanceUpdateCallback | undefined;\n\n constructor(\n multicallClient: MulticallClient,\n messenger: BalanceFetcherMessenger,\n config?: BalanceFetcherConfig,\n ) {\n super();\n this.#multicallClient = multicallClient;\n this.#messenger = messenger;\n this.#config = {\n defaultBatchSize: config?.defaultBatchSize ?? 300,\n defaultTimeoutMs: config?.defaultTimeoutMs ?? 30000,\n includeNativeByDefault: config?.includeNativeByDefault ?? true,\n };\n\n // Set the polling interval\n this.setIntervalLength(config?.pollingInterval ?? DEFAULT_BALANCE_INTERVAL);\n }\n\n /**\n * Set the callback to receive balance updates during polling.\n *\n * @param callback - Function to call with balance results.\n */\n setOnBalanceUpdate(callback: OnBalanceUpdateCallback): void {\n this.#onBalanceUpdate = callback;\n }\n\n /**\n * Execute a poll cycle (required by base class).\n * Fetches balances and calls the update callback.\n *\n * @param input - The polling input.\n */\n async _executePoll(input: BalancePollingInput): Promise<void> {\n const result = await this.fetchBalances(\n input.chainId,\n input.accountId,\n input.accountAddress,\n );\n\n if (this.#onBalanceUpdate && result.balances.length > 0) {\n await this.#onBalanceUpdate(result);\n }\n }\n\n getTokensToFetch(chainId: ChainId, accountId: AccountId): TokenFetchInfo[] {\n const state = this.#messenger.call('AssetsController:getState');\n\n if (!state?.assetsBalance) {\n return [];\n }\n\n const accountBalances = state.assetsBalance[accountId];\n if (!accountBalances) {\n return [];\n }\n\n // Convert hex chainId to decimal for CAIP-2 matching\n const chainIdDecimal = parseInt(chainId, 16);\n const caipChainPrefix = `eip155:${chainIdDecimal}/`;\n\n const tokenMap = new Map<string, TokenFetchInfo>();\n\n for (const assetId of Object.keys(accountBalances)) {\n // Only process ERC20 tokens on the current chain\n if (assetId.startsWith(caipChainPrefix) && assetId.includes('/erc20:')) {\n // Parse token address from CAIP-19: eip155:1/erc20:0x...\n const tokenAddress = assetId.split('/erc20:')[1] as Address;\n if (tokenAddress) {\n const lowerAddress = tokenAddress.toLowerCase();\n if (!tokenMap.has(lowerAddress)) {\n tokenMap.set(lowerAddress, {\n address: tokenAddress,\n symbol: '',\n });\n }\n }\n }\n }\n\n return Array.from(tokenMap.values());\n }\n\n async fetchBalances(\n chainId: ChainId,\n accountId: AccountId,\n accountAddress: Address,\n options?: BalanceFetchOptions,\n ): Promise<BalanceFetchResult> {\n const tokens = this.getTokensToFetch(chainId, accountId);\n const tokenAddresses = tokens.map((token) => token.address);\n\n return this.fetchBalancesForTokens(\n chainId,\n accountId,\n accountAddress,\n tokenAddresses,\n options,\n tokens,\n );\n }\n\n async fetchBalancesForTokens(\n chainId: ChainId,\n accountId: AccountId,\n accountAddress: Address,\n tokenAddresses: Address[],\n options?: BalanceFetchOptions,\n tokenInfos?: TokenFetchInfo[],\n ): Promise<BalanceFetchResult> {\n const batchSize = options?.batchSize ?? this.#config.defaultBatchSize;\n const includeNative =\n options?.includeNative ?? this.#config.includeNativeByDefault;\n const timestamp = Date.now();\n\n const tokenInfoMap = new Map<string, TokenFetchInfo>();\n if (tokenInfos) {\n for (const info of tokenInfos) {\n tokenInfoMap.set(info.address.toLowerCase(), info);\n }\n }\n\n const balanceRequests: BalanceOfRequest[] = [];\n\n if (includeNative) {\n balanceRequests.push({\n tokenAddress: ZERO_ADDRESS,\n accountAddress,\n });\n }\n\n for (const tokenAddress of tokenAddresses) {\n balanceRequests.push({\n tokenAddress,\n accountAddress,\n });\n }\n\n if (balanceRequests.length === 0) {\n return {\n chainId,\n accountId,\n accountAddress,\n balances: [],\n failedAddresses: [],\n timestamp,\n };\n }\n\n type FetchAccumulator = {\n balances: AssetBalance[];\n failedAddresses: Address[];\n };\n\n const result = await reduceInBatchesSerially<\n BalanceOfRequest,\n FetchAccumulator\n >({\n values: balanceRequests,\n batchSize,\n initialResult: {\n balances: [],\n failedAddresses: [],\n },\n eachBatch: async (workingResult, batch) => {\n const responses = await this.#multicallClient.batchBalanceOf(\n chainId,\n batch,\n );\n\n return this.#processBalanceResponses(\n responses,\n workingResult as FetchAccumulator,\n chainId,\n accountId,\n timestamp,\n tokenInfoMap,\n );\n },\n });\n\n return {\n chainId,\n accountId,\n accountAddress,\n ...result,\n timestamp,\n };\n }\n\n #processBalanceResponses(\n responses: BalanceOfResponse[],\n accumulator: {\n balances: AssetBalance[];\n failedAddresses: Address[];\n },\n chainId: ChainId,\n accountId: AccountId,\n timestamp: number,\n tokenInfoMap: Map<string, TokenFetchInfo>,\n ): {\n balances: AssetBalance[];\n failedAddresses: Address[];\n } {\n const { balances, failedAddresses } = accumulator;\n\n for (const response of responses) {\n if (!response.success) {\n failedAddresses.push(response.tokenAddress);\n continue;\n }\n\n const balance = response.balance ?? '0';\n const chainIdDecimal = parseInt(chainId, 16);\n const isNative =\n response.tokenAddress.toLowerCase() === ZERO_ADDRESS.toLowerCase();\n const tokenInfo = tokenInfoMap.get(response.tokenAddress.toLowerCase());\n\n // Native uses 18. ERC-20: format when decimals are known; otherwise pass raw\n // `balance` through so RpcDataSource can resolve decimals (state → list → RPC).\n let decimals: number | undefined;\n let formattedBalance: string;\n if (isNative) {\n decimals = 18;\n formattedBalance = this.#formatBalance(balance, decimals);\n } else if (tokenInfo?.decimals === undefined) {\n formattedBalance = balance;\n } else {\n decimals = tokenInfo.decimals;\n formattedBalance = this.#formatBalance(balance, decimals);\n }\n const assetId: CaipAssetType = isNative\n ? (`eip155:${chainIdDecimal}/slip44:60` as CaipAssetType)\n : (`eip155:${chainIdDecimal}/erc20:${response.tokenAddress.toLowerCase()}` as CaipAssetType);\n\n const balanceEntry: AssetBalance = {\n assetId,\n accountId,\n chainId,\n balance,\n formattedBalance,\n timestamp,\n };\n if (typeof decimals === 'number') {\n balanceEntry.decimals = decimals;\n }\n balances.push(balanceEntry);\n }\n\n return { balances, failedAddresses };\n }\n\n #formatBalance(rawBalance: string, decimals: number): string {\n if (rawBalance === '0') {\n return '0';\n }\n\n try {\n const balanceBigInt = BigInt(rawBalance);\n const divisor = BigInt(10 ** decimals);\n\n const integerPart = balanceBigInt / divisor;\n const remainder = balanceBigInt % divisor;\n const fractionalStr = remainder.toString().padStart(decimals, '0');\n const trimmedFractional = fractionalStr.replace(/0+$/u, '');\n\n if (trimmedFractional === '') {\n return integerPart.toString();\n }\n\n return `${integerPart}.${trimmedFractional}`;\n } catch {\n return rawBalance;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BalanceFetcher.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/BalanceFetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { StaticIntervalPollingControllerOnly } from '@metamask/polling-controller';\nimport { parseCaipAssetType } from '@metamask/utils';\n\nimport { ZERO_ADDRESS } from '../../../utils/constants';\nimport type { MulticallClient } from '../clients';\nimport type {\n AccountId,\n Address,\n AssetBalance,\n AssetFetchEntry,\n AssetsBalanceState,\n BalanceFetchResult,\n BalanceOfRequest,\n BalanceOfResponse,\n CaipAssetType,\n ChainId,\n} from '../types';\nimport { reduceInBatchesSerially } from '../utils';\n\nconst DEFAULT_BALANCE_INTERVAL = 30_000; // 30 seconds\n\n/**\n * Minimal messenger interface for BalanceFetcher.\n */\nexport type BalanceFetcherMessenger = {\n call: (action: 'AssetsController:getState') => AssetsBalanceState;\n};\n\nexport type BalanceFetcherConfig = {\n defaultBatchSize?: number;\n defaultTimeoutMs?: number;\n /** Polling interval in ms (default: 30s) */\n pollingInterval?: number;\n};\n\n/**\n * Polling input for BalanceFetcher - identifies what to poll for.\n */\nexport type BalancePollingInput = {\n /** Chain ID (hex format) */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n};\n\n/**\n * Callback type for balance updates.\n */\nexport type OnBalanceUpdateCallback = (\n result: BalanceFetchResult,\n) => void | Promise<void>;\n\n/**\n * BalanceFetcher - Fetches token balances via multicall.\n * Extends StaticIntervalPollingControllerOnly for built-in polling support.\n *\n * Callers provide CAIP-19 asset IDs; the fetcher extracts on-chain addresses\n * (or uses the zero address for native assets) and maps multicall responses\n * back to the original asset IDs. This ensures the returned balance entries\n * always carry the correct identifier regardless of chain.\n */\nexport class BalanceFetcher extends StaticIntervalPollingControllerOnly<BalancePollingInput>() {\n readonly #multicallClient: MulticallClient;\n\n readonly #messenger: BalanceFetcherMessenger;\n\n readonly #config: Required<Omit<BalanceFetcherConfig, 'pollingInterval'>>;\n\n #onBalanceUpdate: OnBalanceUpdateCallback | undefined;\n\n constructor(\n multicallClient: MulticallClient,\n messenger: BalanceFetcherMessenger,\n config?: BalanceFetcherConfig,\n ) {\n super();\n this.#multicallClient = multicallClient;\n this.#messenger = messenger;\n this.#config = {\n defaultBatchSize: config?.defaultBatchSize ?? 300,\n defaultTimeoutMs: config?.defaultTimeoutMs ?? 30000,\n };\n\n // Set the polling interval\n this.setIntervalLength(config?.pollingInterval ?? DEFAULT_BALANCE_INTERVAL);\n }\n\n /**\n * Set the callback to receive balance updates during polling.\n *\n * @param callback - Function to call with balance results.\n */\n setOnBalanceUpdate(callback: OnBalanceUpdateCallback): void {\n this.#onBalanceUpdate = callback;\n }\n\n /**\n * Execute a poll cycle (required by base class).\n * Fetches balances and calls the update callback.\n *\n * @param input - The polling input.\n */\n async _executePoll(input: BalancePollingInput): Promise<void> {\n const result = await this.#fetchBalances(\n input.chainId,\n input.accountId,\n input.accountAddress,\n );\n\n if (this.#onBalanceUpdate && result.balances.length > 0) {\n await this.#onBalanceUpdate(result);\n }\n }\n\n /**\n * Return asset fetch entries tracked in state for the given account and\n * chain. Both native (`slip44:`) and ERC-20 (`erc20:`) entries are included.\n *\n * @param chainId - Hex chain ID (e.g. \"0x1\").\n * @param accountId - Account UUID.\n * @returns Array of asset fetch entries from state for the requested chain.\n */\n #getAssetsToFetch(chainId: ChainId, accountId: AccountId): AssetFetchEntry[] {\n const state = this.#messenger.call('AssetsController:getState');\n\n const accountBalances = state?.assetsBalance?.[accountId];\n if (!accountBalances) {\n return [];\n }\n\n // Convert hex chainId to decimal for CAIP-2 matching\n // This is safe because we are filtring with an accountId that is for evm balances only\n const chainIdDecimal = parseInt(chainId, 16).toString();\n\n const assetsToFetch = new Map<string, AssetFetchEntry>();\n\n for (const assetId of Object.keys(accountBalances) as CaipAssetType[]) {\n const {\n chain: { reference: chainReference },\n assetNamespace,\n assetReference,\n } = parseCaipAssetType(assetId);\n\n if (chainReference === chainIdDecimal) {\n const assetIdLowerCase = assetId.toLowerCase();\n if (assetsToFetch.has(assetIdLowerCase)) {\n continue;\n }\n\n const isNative = assetNamespace === 'slip44';\n const tokenAddress = isNative\n ? ZERO_ADDRESS\n : (assetReference.toLowerCase() as Address);\n\n assetsToFetch.set(assetIdLowerCase, {\n assetId,\n address: tokenAddress,\n });\n }\n }\n\n return Array.from(assetsToFetch.values());\n }\n\n /**\n * Fetch balances for assets already tracked in state for the given\n * account and chain.\n *\n * @param chainId - Hex chain ID.\n * @param accountId - Account UUID.\n * @param accountAddress - On-chain address of the account.\n * @returns Balance fetch result.\n */\n async #fetchBalances(\n chainId: ChainId,\n accountId: AccountId,\n accountAddress: Address,\n ): Promise<BalanceFetchResult> {\n const assets = this.#getAssetsToFetch(chainId, accountId);\n\n return this.fetchBalancesForAssets(\n chainId,\n accountId,\n accountAddress,\n assets,\n );\n }\n\n /**\n * Fetch balances for the given assets via multicall.\n *\n * Each entry bundles a CAIP-19 asset ID with its on-chain address and\n * optional decimals.\n *\n * @param chainId - Hex chain ID.\n * @param accountId - Account UUID.\n * @param accountAddress - On-chain address of the account.\n * @param assets - Asset fetch entries to fetch balances for.\n * @returns Balance fetch result.\n */\n async fetchBalancesForAssets(\n chainId: ChainId,\n accountId: AccountId,\n accountAddress: Address,\n assets: AssetFetchEntry[],\n ): Promise<BalanceFetchResult> {\n const timestamp = Date.now();\n\n // Build a single map keyed by lowercase address that holds all info\n // needed to match multicall responses back to their original entries.\n const balanceRequests: BalanceOfRequest[] = [];\n const entryByAddress = new Map<string, AssetFetchEntry>();\n\n for (const entry of assets) {\n const lowerAddress = entry.address.toLowerCase();\n if (entryByAddress.has(lowerAddress)) {\n continue; // deduplicate\n }\n\n entryByAddress.set(lowerAddress, entry);\n balanceRequests.push({ tokenAddress: entry.address, accountAddress });\n }\n\n if (balanceRequests.length === 0) {\n return {\n chainId,\n accountId,\n accountAddress,\n balances: [],\n failedAddresses: [],\n timestamp,\n };\n }\n\n type FetchAccumulator = {\n balances: AssetBalance[];\n failedAddresses: Address[];\n };\n\n const result = await reduceInBatchesSerially<\n BalanceOfRequest,\n FetchAccumulator\n >({\n values: balanceRequests,\n batchSize: this.#config.defaultBatchSize,\n initialResult: {\n balances: [],\n failedAddresses: [],\n },\n eachBatch: async (workingResult, batch) => {\n const responses = await this.#multicallClient.batchBalanceOf(\n chainId,\n batch,\n );\n\n return this.#processBalanceResponses(\n responses,\n workingResult as FetchAccumulator,\n chainId,\n accountId,\n timestamp,\n entryByAddress,\n );\n },\n });\n\n return {\n chainId,\n accountId,\n accountAddress,\n ...result,\n timestamp,\n };\n }\n\n #processBalanceResponses(\n responses: BalanceOfResponse[],\n accumulator: {\n balances: AssetBalance[];\n failedAddresses: Address[];\n },\n chainId: ChainId,\n accountId: AccountId,\n timestamp: number,\n entryByAddress: Map<string, AssetFetchEntry>,\n ): {\n balances: AssetBalance[];\n failedAddresses: Address[];\n } {\n const { balances, failedAddresses } = accumulator;\n\n for (const response of responses) {\n if (!response.success) {\n failedAddresses.push(response.tokenAddress);\n continue;\n }\n\n const lowerAddress = response.tokenAddress.toLowerCase();\n const entry = entryByAddress.get(lowerAddress);\n if (!entry) {\n continue;\n }\n\n const balance = response.balance ?? '0';\n const isNative = lowerAddress === ZERO_ADDRESS.toLowerCase();\n\n let decimals: number | undefined;\n let formattedBalance: string;\n if (isNative) {\n decimals = 18;\n formattedBalance = this.#formatBalance(balance, decimals);\n } else if (entry.decimals === undefined) {\n formattedBalance = balance;\n } else {\n decimals = entry.decimals;\n formattedBalance = this.#formatBalance(balance, decimals);\n }\n\n const balanceEntry: AssetBalance = {\n assetId: entry.assetId,\n accountId,\n chainId,\n balance,\n formattedBalance,\n timestamp,\n };\n if (typeof decimals === 'number') {\n balanceEntry.decimals = decimals;\n }\n balances.push(balanceEntry);\n }\n\n return { balances, failedAddresses };\n }\n\n #formatBalance(rawBalance: string, decimals: number): string {\n if (rawBalance === '0') {\n return '0';\n }\n\n try {\n const balanceBigInt = BigInt(rawBalance);\n const divisor = BigInt(10 ** decimals);\n\n const integerPart = balanceBigInt / divisor;\n const remainder = balanceBigInt % divisor;\n const fractionalStr = remainder.toString().padStart(decimals, '0');\n const trimmedFractional = fractionalStr.replace(/0+$/u, '');\n\n if (trimmedFractional === '') {\n return integerPart.toString();\n }\n\n return `${integerPart}.${trimmedFractional}`;\n } catch {\n return rawBalance;\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/index.ts"],"names":[],"mappings":"","sourcesContent":["// Core types\nexport type {\n AccountId,\n Address,\n AssetType,\n CaipAssetType,\n ChainId,\n} from './core';\n\n// Asset types\nexport type { Asset, AssetBalance } from './assets';\n\n// State types\nexport type {\n AssetsBalanceState,\n TokenChainsCacheEntry,\n TokenListEntry,\n TokenListState,\n} from './state';\n\n// Config types\nexport type { GetProviderFunction, Provider } from './config';\n\n// Multicall types\nexport type { BalanceOfRequest, BalanceOfResponse } from './multicall';\n\n// Service types\nexport type {\n
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/index.ts"],"names":[],"mappings":"","sourcesContent":["// Core types\nexport type {\n AccountId,\n Address,\n AssetType,\n CaipAssetType,\n ChainId,\n} from './core';\n\n// Asset types\nexport type { Asset, AssetBalance } from './assets';\n\n// State types\nexport type {\n AssetsBalanceState,\n TokenChainsCacheEntry,\n TokenListEntry,\n TokenListState,\n} from './state';\n\n// Config types\nexport type { GetProviderFunction, Provider } from './config';\n\n// Multicall types\nexport type { BalanceOfRequest, BalanceOfResponse } from './multicall';\n\n// Service types\nexport type {\n AssetFetchEntry,\n BalanceFetchResult,\n TokenDetectionOptions,\n TokenDetectionResult,\n} from './services';\n"]}
|
|
@@ -3,5 +3,5 @@ export type { Asset, AssetBalance } from "./assets.cjs";
|
|
|
3
3
|
export type { AssetsBalanceState, TokenChainsCacheEntry, TokenListEntry, TokenListState, } from "./state.cjs";
|
|
4
4
|
export type { GetProviderFunction, Provider } from "./config.cjs";
|
|
5
5
|
export type { BalanceOfRequest, BalanceOfResponse } from "./multicall.cjs";
|
|
6
|
-
export type {
|
|
6
|
+
export type { AssetFetchEntry, BalanceFetchResult, TokenDetectionOptions, TokenDetectionResult, } from "./services.cjs";
|
|
7
7
|
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,OAAO,EACP,SAAS,EACT,aAAa,EACb,OAAO,GACR,mBAAe;AAGhB,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAiB;AAGpD,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,cAAc,GACf,oBAAgB;AAGjB,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,qBAAiB;AAG9D,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAoB;AAGvE,YAAY,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,OAAO,EACP,SAAS,EACT,aAAa,EACb,OAAO,GACR,mBAAe;AAGhB,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAiB;AAGpD,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,cAAc,GACf,oBAAgB;AAGjB,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,qBAAiB;AAG9D,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAoB;AAGvE,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,GACrB,uBAAmB"}
|
|
@@ -3,5 +3,5 @@ export type { Asset, AssetBalance } from "./assets.mjs";
|
|
|
3
3
|
export type { AssetsBalanceState, TokenChainsCacheEntry, TokenListEntry, TokenListState, } from "./state.mjs";
|
|
4
4
|
export type { GetProviderFunction, Provider } from "./config.mjs";
|
|
5
5
|
export type { BalanceOfRequest, BalanceOfResponse } from "./multicall.mjs";
|
|
6
|
-
export type {
|
|
6
|
+
export type { AssetFetchEntry, BalanceFetchResult, TokenDetectionOptions, TokenDetectionResult, } from "./services.mjs";
|
|
7
7
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,OAAO,EACP,SAAS,EACT,aAAa,EACb,OAAO,GACR,mBAAe;AAGhB,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAiB;AAGpD,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,cAAc,GACf,oBAAgB;AAGjB,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,qBAAiB;AAG9D,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAoB;AAGvE,YAAY,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,OAAO,EACP,SAAS,EACT,aAAa,EACb,OAAO,GACR,mBAAe;AAGhB,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAiB;AAGpD,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,cAAc,GACf,oBAAgB;AAGjB,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,qBAAiB;AAG9D,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAoB;AAGvE,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,GACrB,uBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/index.ts"],"names":[],"mappings":"","sourcesContent":["// Core types\nexport type {\n AccountId,\n Address,\n AssetType,\n CaipAssetType,\n ChainId,\n} from './core';\n\n// Asset types\nexport type { Asset, AssetBalance } from './assets';\n\n// State types\nexport type {\n AssetsBalanceState,\n TokenChainsCacheEntry,\n TokenListEntry,\n TokenListState,\n} from './state';\n\n// Config types\nexport type { GetProviderFunction, Provider } from './config';\n\n// Multicall types\nexport type { BalanceOfRequest, BalanceOfResponse } from './multicall';\n\n// Service types\nexport type {\n
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/index.ts"],"names":[],"mappings":"","sourcesContent":["// Core types\nexport type {\n AccountId,\n Address,\n AssetType,\n CaipAssetType,\n ChainId,\n} from './core';\n\n// Asset types\nexport type { Asset, AssetBalance } from './assets';\n\n// State types\nexport type {\n AssetsBalanceState,\n TokenChainsCacheEntry,\n TokenListEntry,\n TokenListState,\n} from './state';\n\n// Config types\nexport type { GetProviderFunction, Provider } from './config';\n\n// Multicall types\nexport type { BalanceOfRequest, BalanceOfResponse } from './multicall';\n\n// Service types\nexport type {\n AssetFetchEntry,\n BalanceFetchResult,\n TokenDetectionOptions,\n TokenDetectionResult,\n} from './services';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/services.ts"],"names":[],"mappings":"","sourcesContent":["import type { Asset, AssetBalance } from './assets';\nimport type { AccountId, Address, ChainId } from './core';\n\n/**\n * Token detection result.\n */\nexport type TokenDetectionResult = {\n /** Chain ID */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address used for detection */\n accountAddress: Address;\n /** Newly detected tokens with non-zero balances */\n detectedAssets: Asset[];\n /** Balances for newly detected tokens */\n detectedBalances: AssetBalance[];\n /** Tokens that were checked but had zero balance */\n zeroBalanceAddresses: Address[];\n /** Tokens that failed to be checked */\n failedAddresses: Address[];\n /** Timestamp of detection */\n timestamp: number;\n};\n\n/**\n * Token detection options.\n */\nexport type TokenDetectionOptions = {\n /** Whether token detection is enabled */\n tokenDetectionEnabled?: boolean;\n /** Whether external services (e.g. token list API) are allowed; detection stops when false */\n useExternalService?: boolean;\n /** Maximum number of tokens to check per batch */\n batchSize?: number;\n /** Timeout for detection in milliseconds */\n timeout?: number;\n};\n\n/**\n * Balance fetch result.\n */\nexport type BalanceFetchResult = {\n /** Chain ID */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n /** Fetched balances */\n balances: AssetBalance[];\n /** Token addresses that failed to fetch */\n failedAddresses: Address[];\n /** Block number when balances were fetched */\n blockNumber?: number;\n /** Timestamp of fetch */\n timestamp: number;\n};\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"services.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/services.ts"],"names":[],"mappings":"","sourcesContent":["import type { Asset, AssetBalance } from './assets';\nimport type { AccountId, Address, CaipAssetType, ChainId } from './core';\n\n/**\n * Token detection result.\n */\nexport type TokenDetectionResult = {\n /** Chain ID */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address used for detection */\n accountAddress: Address;\n /** Newly detected tokens with non-zero balances */\n detectedAssets: Asset[];\n /** Balances for newly detected tokens */\n detectedBalances: AssetBalance[];\n /** Tokens that were checked but had zero balance */\n zeroBalanceAddresses: Address[];\n /** Tokens that failed to be checked */\n failedAddresses: Address[];\n /** Timestamp of detection */\n timestamp: number;\n};\n\n/**\n * Token detection options.\n */\nexport type TokenDetectionOptions = {\n /** Whether token detection is enabled */\n tokenDetectionEnabled?: boolean;\n /** Whether external services (e.g. token list API) are allowed; detection stops when false */\n useExternalService?: boolean;\n /** Maximum number of tokens to check per batch */\n batchSize?: number;\n /** Timeout for detection in milliseconds */\n timeout?: number;\n};\n\n/**\n * Balance fetch result.\n */\nexport type BalanceFetchResult = {\n /** Chain ID */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n /** Fetched balances */\n balances: AssetBalance[];\n /** Token addresses that failed to fetch */\n failedAddresses: Address[];\n /** Block number when balances were fetched */\n blockNumber?: number;\n /** Timestamp of fetch */\n timestamp: number;\n};\n\n/**\n * Entry describing a single asset to fetch a balance for.\n * Bundles the CAIP-19 asset ID with the on-chain address (zero address for\n * native assets even when the chain has a native asset with a non-zero address)\n * and optional metadata\n */\nexport type AssetFetchEntry = {\n /** CAIP-19 asset type identifier */\n assetId: CaipAssetType;\n /** On-chain contract address (zero address for native assets regardless of the chain's native asset address) */\n address: Address;\n /** Token decimals (omit when unknown — balance fetcher returns raw balance for RpcDataSource to resolve). */\n decimals?: number;\n};\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Asset, AssetBalance } from "./assets.cjs";
|
|
2
|
-
import type { AccountId, Address, ChainId } from "./core.cjs";
|
|
2
|
+
import type { AccountId, Address, CaipAssetType, ChainId } from "./core.cjs";
|
|
3
3
|
/**
|
|
4
4
|
* Token detection result.
|
|
5
5
|
*/
|
|
@@ -54,25 +54,17 @@ export type BalanceFetchResult = {
|
|
|
54
54
|
timestamp: number;
|
|
55
55
|
};
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
57
|
+
* Entry describing a single asset to fetch a balance for.
|
|
58
|
+
* Bundles the CAIP-19 asset ID with the on-chain address (zero address for
|
|
59
|
+
* native assets even when the chain has a native asset with a non-zero address)
|
|
60
|
+
* and optional metadata
|
|
58
61
|
*/
|
|
59
|
-
export type
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
timeout?: number;
|
|
64
|
-
/** Include native token balance */
|
|
65
|
-
includeNative?: boolean;
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Token info for balance fetching.
|
|
69
|
-
*/
|
|
70
|
-
export type TokenFetchInfo = {
|
|
71
|
-
/** Token contract address */
|
|
62
|
+
export type AssetFetchEntry = {
|
|
63
|
+
/** CAIP-19 asset type identifier */
|
|
64
|
+
assetId: CaipAssetType;
|
|
65
|
+
/** On-chain contract address (zero address for native assets regardless of the chain's native asset address) */
|
|
72
66
|
address: Address;
|
|
73
67
|
/** Token decimals (omit when unknown — balance fetcher returns raw balance for RpcDataSource to resolve). */
|
|
74
68
|
decimals?: number;
|
|
75
|
-
/** Token symbol (optional) */
|
|
76
|
-
symbol?: string;
|
|
77
69
|
};
|
|
78
70
|
//# sourceMappingURL=services.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAiB;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAe;
|
|
1
|
+
{"version":3,"file":"services.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAiB;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAe;AAEzE;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,yCAAyC;IACzC,cAAc,EAAE,OAAO,CAAC;IACxB,mDAAmD;IACnD,cAAc,EAAE,KAAK,EAAE,CAAC;IACxB,yCAAyC;IACzC,gBAAgB,EAAE,YAAY,EAAE,CAAC;IACjC,oDAAoD;IACpD,oBAAoB,EAAE,OAAO,EAAE,CAAC;IAChC,uCAAuC;IACvC,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,yCAAyC;IACzC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,8FAA8F;IAC9F,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,uBAAuB;IACvB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,2CAA2C;IAC3C,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,oCAAoC;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,gHAAgH;IAChH,OAAO,EAAE,OAAO,CAAC;IACjB,6GAA6G;IAC7G,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Asset, AssetBalance } from "./assets.mjs";
|
|
2
|
-
import type { AccountId, Address, ChainId } from "./core.mjs";
|
|
2
|
+
import type { AccountId, Address, CaipAssetType, ChainId } from "./core.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* Token detection result.
|
|
5
5
|
*/
|
|
@@ -54,25 +54,17 @@ export type BalanceFetchResult = {
|
|
|
54
54
|
timestamp: number;
|
|
55
55
|
};
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
57
|
+
* Entry describing a single asset to fetch a balance for.
|
|
58
|
+
* Bundles the CAIP-19 asset ID with the on-chain address (zero address for
|
|
59
|
+
* native assets even when the chain has a native asset with a non-zero address)
|
|
60
|
+
* and optional metadata
|
|
58
61
|
*/
|
|
59
|
-
export type
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
timeout?: number;
|
|
64
|
-
/** Include native token balance */
|
|
65
|
-
includeNative?: boolean;
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Token info for balance fetching.
|
|
69
|
-
*/
|
|
70
|
-
export type TokenFetchInfo = {
|
|
71
|
-
/** Token contract address */
|
|
62
|
+
export type AssetFetchEntry = {
|
|
63
|
+
/** CAIP-19 asset type identifier */
|
|
64
|
+
assetId: CaipAssetType;
|
|
65
|
+
/** On-chain contract address (zero address for native assets regardless of the chain's native asset address) */
|
|
72
66
|
address: Address;
|
|
73
67
|
/** Token decimals (omit when unknown — balance fetcher returns raw balance for RpcDataSource to resolve). */
|
|
74
68
|
decimals?: number;
|
|
75
|
-
/** Token symbol (optional) */
|
|
76
|
-
symbol?: string;
|
|
77
69
|
};
|
|
78
70
|
//# sourceMappingURL=services.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAiB;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAe;
|
|
1
|
+
{"version":3,"file":"services.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAiB;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAe;AAEzE;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,yCAAyC;IACzC,cAAc,EAAE,OAAO,CAAC;IACxB,mDAAmD;IACnD,cAAc,EAAE,KAAK,EAAE,CAAC;IACxB,yCAAyC;IACzC,gBAAgB,EAAE,YAAY,EAAE,CAAC;IACjC,oDAAoD;IACpD,oBAAoB,EAAE,OAAO,EAAE,CAAC;IAChC,uCAAuC;IACvC,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,yCAAyC;IACzC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,8FAA8F;IAC9F,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,uBAAuB;IACvB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,2CAA2C;IAC3C,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,oCAAoC;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,gHAAgH;IAChH,OAAO,EAAE,OAAO,CAAC;IACjB,6GAA6G;IAC7G,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/services.ts"],"names":[],"mappings":"","sourcesContent":["import type { Asset, AssetBalance } from './assets';\nimport type { AccountId, Address, ChainId } from './core';\n\n/**\n * Token detection result.\n */\nexport type TokenDetectionResult = {\n /** Chain ID */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address used for detection */\n accountAddress: Address;\n /** Newly detected tokens with non-zero balances */\n detectedAssets: Asset[];\n /** Balances for newly detected tokens */\n detectedBalances: AssetBalance[];\n /** Tokens that were checked but had zero balance */\n zeroBalanceAddresses: Address[];\n /** Tokens that failed to be checked */\n failedAddresses: Address[];\n /** Timestamp of detection */\n timestamp: number;\n};\n\n/**\n * Token detection options.\n */\nexport type TokenDetectionOptions = {\n /** Whether token detection is enabled */\n tokenDetectionEnabled?: boolean;\n /** Whether external services (e.g. token list API) are allowed; detection stops when false */\n useExternalService?: boolean;\n /** Maximum number of tokens to check per batch */\n batchSize?: number;\n /** Timeout for detection in milliseconds */\n timeout?: number;\n};\n\n/**\n * Balance fetch result.\n */\nexport type BalanceFetchResult = {\n /** Chain ID */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n /** Fetched balances */\n balances: AssetBalance[];\n /** Token addresses that failed to fetch */\n failedAddresses: Address[];\n /** Block number when balances were fetched */\n blockNumber?: number;\n /** Timestamp of fetch */\n timestamp: number;\n};\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"services.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/types/services.ts"],"names":[],"mappings":"","sourcesContent":["import type { Asset, AssetBalance } from './assets';\nimport type { AccountId, Address, CaipAssetType, ChainId } from './core';\n\n/**\n * Token detection result.\n */\nexport type TokenDetectionResult = {\n /** Chain ID */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address used for detection */\n accountAddress: Address;\n /** Newly detected tokens with non-zero balances */\n detectedAssets: Asset[];\n /** Balances for newly detected tokens */\n detectedBalances: AssetBalance[];\n /** Tokens that were checked but had zero balance */\n zeroBalanceAddresses: Address[];\n /** Tokens that failed to be checked */\n failedAddresses: Address[];\n /** Timestamp of detection */\n timestamp: number;\n};\n\n/**\n * Token detection options.\n */\nexport type TokenDetectionOptions = {\n /** Whether token detection is enabled */\n tokenDetectionEnabled?: boolean;\n /** Whether external services (e.g. token list API) are allowed; detection stops when false */\n useExternalService?: boolean;\n /** Maximum number of tokens to check per batch */\n batchSize?: number;\n /** Timeout for detection in milliseconds */\n timeout?: number;\n};\n\n/**\n * Balance fetch result.\n */\nexport type BalanceFetchResult = {\n /** Chain ID */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n /** Fetched balances */\n balances: AssetBalance[];\n /** Token addresses that failed to fetch */\n failedAddresses: Address[];\n /** Block number when balances were fetched */\n blockNumber?: number;\n /** Timestamp of fetch */\n timestamp: number;\n};\n\n/**\n * Entry describing a single asset to fetch a balance for.\n * Bundles the CAIP-19 asset ID with the on-chain address (zero address for\n * native assets even when the chain has a native asset with a non-zero address)\n * and optional metadata\n */\nexport type AssetFetchEntry = {\n /** CAIP-19 asset type identifier */\n assetId: CaipAssetType;\n /** On-chain contract address (zero address for native assets regardless of the chain's native asset address) */\n address: Address;\n /** Token decimals (omit when unknown — balance fetcher returns raw balance for RpcDataSource to resolve). */\n decimals?: number;\n};\n"]}
|
|
@@ -7,6 +7,10 @@ exports.getAggregatedBalanceForAccount = exports.getInternalAccountsForGroup = e
|
|
|
7
7
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
8
8
|
const utils_1 = require("@metamask/utils");
|
|
9
9
|
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// TRACE NAMES — used in Sentry spans (search these strings in Discover)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
const TRACE_AGGREGATED_BALANCE_SELECTOR = 'AggregatedBalanceSelector';
|
|
10
14
|
const ZERO_PRICE = { price: 0, pricePercentChange1d: 0 };
|
|
11
15
|
const getAmountFromBalance = (balance) => {
|
|
12
16
|
if (typeof balance === 'object' && balance !== null && 'amount' in balance) {
|
|
@@ -234,7 +238,8 @@ function resolveAccountsToAggregate(args) {
|
|
|
234
238
|
}
|
|
235
239
|
return [selectedInternalAccount];
|
|
236
240
|
}
|
|
237
|
-
function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledNetworkMap, accountTreeState, internalAccountsOrAccountIds, accountsById) {
|
|
241
|
+
function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledNetworkMap, accountTreeState, internalAccountsOrAccountIds, accountsById, trace) {
|
|
242
|
+
const startTime = trace ? performance.now() : 0;
|
|
238
243
|
const { assetsBalance, assetsInfo, assetPreferences, assetsPrice } = state;
|
|
239
244
|
const metadata = (assetsInfo ?? {});
|
|
240
245
|
const hasPrices = Boolean(assetsPrice) &&
|
|
@@ -292,6 +297,26 @@ function getAggregatedBalanceForAccount(state, selectedInternalAccount, enabledN
|
|
|
292
297
|
}
|
|
293
298
|
}
|
|
294
299
|
}
|
|
300
|
+
if (trace) {
|
|
301
|
+
const durationMs = performance.now() - startTime;
|
|
302
|
+
const uniqueNetworks = new Set();
|
|
303
|
+
for (const assetId of merged.keys()) {
|
|
304
|
+
const info = getAssetInfo(assetInfoCache, assetId);
|
|
305
|
+
uniqueNetworks.add(info.chainId);
|
|
306
|
+
}
|
|
307
|
+
trace({
|
|
308
|
+
name: TRACE_AGGREGATED_BALANCE_SELECTOR,
|
|
309
|
+
data: {
|
|
310
|
+
duration_ms: durationMs,
|
|
311
|
+
asset_count: merged.size,
|
|
312
|
+
network_count: uniqueNetworks.size,
|
|
313
|
+
account_count: accountsToAggregate.length,
|
|
314
|
+
},
|
|
315
|
+
tags: { controller: 'AssetsController' },
|
|
316
|
+
}, () => undefined).catch(() => {
|
|
317
|
+
// Telemetry failure must not break.
|
|
318
|
+
});
|
|
319
|
+
}
|
|
295
320
|
if (hasPrices) {
|
|
296
321
|
const pricePercentChange1d = totalBalanceInFiat > 0 ? weightedNumerator / totalBalanceInFiat : 0;
|
|
297
322
|
return {
|