@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
|
@@ -10,16 +10,22 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
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");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _BalanceFetcher_instances, _BalanceFetcher_multicallClient, _BalanceFetcher_messenger, _BalanceFetcher_config, _BalanceFetcher_onBalanceUpdate, _BalanceFetcher_processBalanceResponses, _BalanceFetcher_formatBalance;
|
|
13
|
+
var _BalanceFetcher_instances, _BalanceFetcher_multicallClient, _BalanceFetcher_messenger, _BalanceFetcher_config, _BalanceFetcher_onBalanceUpdate, _BalanceFetcher_getAssetsToFetch, _BalanceFetcher_fetchBalances, _BalanceFetcher_processBalanceResponses, _BalanceFetcher_formatBalance;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.BalanceFetcher = void 0;
|
|
16
16
|
const polling_controller_1 = require("@metamask/polling-controller");
|
|
17
|
-
const utils_1 = require("
|
|
17
|
+
const utils_1 = require("@metamask/utils");
|
|
18
|
+
const constants_1 = require("../../../utils/constants.cjs");
|
|
19
|
+
const utils_2 = require("../utils/index.cjs");
|
|
18
20
|
const DEFAULT_BALANCE_INTERVAL = 30000; // 30 seconds
|
|
19
|
-
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
20
21
|
/**
|
|
21
22
|
* BalanceFetcher - Fetches token balances via multicall.
|
|
22
23
|
* Extends StaticIntervalPollingControllerOnly for built-in polling support.
|
|
24
|
+
*
|
|
25
|
+
* Callers provide CAIP-19 asset IDs; the fetcher extracts on-chain addresses
|
|
26
|
+
* (or uses the zero address for native assets) and maps multicall responses
|
|
27
|
+
* back to the original asset IDs. This ensures the returned balance entries
|
|
28
|
+
* always carry the correct identifier regardless of chain.
|
|
23
29
|
*/
|
|
24
30
|
class BalanceFetcher extends (0, polling_controller_1.StaticIntervalPollingControllerOnly)() {
|
|
25
31
|
constructor(multicallClient, messenger, config) {
|
|
@@ -34,7 +40,6 @@ class BalanceFetcher extends (0, polling_controller_1.StaticIntervalPollingContr
|
|
|
34
40
|
__classPrivateFieldSet(this, _BalanceFetcher_config, {
|
|
35
41
|
defaultBatchSize: config?.defaultBatchSize ?? 300,
|
|
36
42
|
defaultTimeoutMs: config?.defaultTimeoutMs ?? 30000,
|
|
37
|
-
includeNativeByDefault: config?.includeNativeByDefault ?? true,
|
|
38
43
|
}, "f");
|
|
39
44
|
// Set the polling interval
|
|
40
45
|
this.setIntervalLength(config?.pollingInterval ?? DEFAULT_BALANCE_INTERVAL);
|
|
@@ -54,69 +59,36 @@ class BalanceFetcher extends (0, polling_controller_1.StaticIntervalPollingContr
|
|
|
54
59
|
* @param input - The polling input.
|
|
55
60
|
*/
|
|
56
61
|
async _executePoll(input) {
|
|
57
|
-
const result = await this.
|
|
62
|
+
const result = await __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_fetchBalances).call(this, input.chainId, input.accountId, input.accountAddress);
|
|
58
63
|
if (__classPrivateFieldGet(this, _BalanceFetcher_onBalanceUpdate, "f") && result.balances.length > 0) {
|
|
59
64
|
await __classPrivateFieldGet(this, _BalanceFetcher_onBalanceUpdate, "f").call(this, result);
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
for (const assetId of Object.keys(accountBalances)) {
|
|
76
|
-
// Only process ERC20 tokens on the current chain
|
|
77
|
-
if (assetId.startsWith(caipChainPrefix) && assetId.includes('/erc20:')) {
|
|
78
|
-
// Parse token address from CAIP-19: eip155:1/erc20:0x...
|
|
79
|
-
const tokenAddress = assetId.split('/erc20:')[1];
|
|
80
|
-
if (tokenAddress) {
|
|
81
|
-
const lowerAddress = tokenAddress.toLowerCase();
|
|
82
|
-
if (!tokenMap.has(lowerAddress)) {
|
|
83
|
-
tokenMap.set(lowerAddress, {
|
|
84
|
-
address: tokenAddress,
|
|
85
|
-
symbol: '',
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return Array.from(tokenMap.values());
|
|
92
|
-
}
|
|
93
|
-
async fetchBalances(chainId, accountId, accountAddress, options) {
|
|
94
|
-
const tokens = this.getTokensToFetch(chainId, accountId);
|
|
95
|
-
const tokenAddresses = tokens.map((token) => token.address);
|
|
96
|
-
return this.fetchBalancesForTokens(chainId, accountId, accountAddress, tokenAddresses, options, tokens);
|
|
97
|
-
}
|
|
98
|
-
async fetchBalancesForTokens(chainId, accountId, accountAddress, tokenAddresses, options, tokenInfos) {
|
|
99
|
-
const batchSize = options?.batchSize ?? __classPrivateFieldGet(this, _BalanceFetcher_config, "f").defaultBatchSize;
|
|
100
|
-
const includeNative = options?.includeNative ?? __classPrivateFieldGet(this, _BalanceFetcher_config, "f").includeNativeByDefault;
|
|
67
|
+
/**
|
|
68
|
+
* Fetch balances for the given assets via multicall.
|
|
69
|
+
*
|
|
70
|
+
* Each entry bundles a CAIP-19 asset ID with its on-chain address and
|
|
71
|
+
* optional decimals.
|
|
72
|
+
*
|
|
73
|
+
* @param chainId - Hex chain ID.
|
|
74
|
+
* @param accountId - Account UUID.
|
|
75
|
+
* @param accountAddress - On-chain address of the account.
|
|
76
|
+
* @param assets - Asset fetch entries to fetch balances for.
|
|
77
|
+
* @returns Balance fetch result.
|
|
78
|
+
*/
|
|
79
|
+
async fetchBalancesForAssets(chainId, accountId, accountAddress, assets) {
|
|
101
80
|
const timestamp = Date.now();
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
for (const info of tokenInfos) {
|
|
105
|
-
tokenInfoMap.set(info.address.toLowerCase(), info);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
81
|
+
// Build a single map keyed by lowercase address that holds all info
|
|
82
|
+
// needed to match multicall responses back to their original entries.
|
|
108
83
|
const balanceRequests = [];
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
balanceRequests.push({
|
|
117
|
-
tokenAddress,
|
|
118
|
-
accountAddress,
|
|
119
|
-
});
|
|
84
|
+
const entryByAddress = new Map();
|
|
85
|
+
for (const entry of assets) {
|
|
86
|
+
const lowerAddress = entry.address.toLowerCase();
|
|
87
|
+
if (entryByAddress.has(lowerAddress)) {
|
|
88
|
+
continue; // deduplicate
|
|
89
|
+
}
|
|
90
|
+
entryByAddress.set(lowerAddress, entry);
|
|
91
|
+
balanceRequests.push({ tokenAddress: entry.address, accountAddress });
|
|
120
92
|
}
|
|
121
93
|
if (balanceRequests.length === 0) {
|
|
122
94
|
return {
|
|
@@ -128,16 +100,16 @@ class BalanceFetcher extends (0, polling_controller_1.StaticIntervalPollingContr
|
|
|
128
100
|
timestamp,
|
|
129
101
|
};
|
|
130
102
|
}
|
|
131
|
-
const result = await (0,
|
|
103
|
+
const result = await (0, utils_2.reduceInBatchesSerially)({
|
|
132
104
|
values: balanceRequests,
|
|
133
|
-
batchSize,
|
|
105
|
+
batchSize: __classPrivateFieldGet(this, _BalanceFetcher_config, "f").defaultBatchSize,
|
|
134
106
|
initialResult: {
|
|
135
107
|
balances: [],
|
|
136
108
|
failedAddresses: [],
|
|
137
109
|
},
|
|
138
110
|
eachBatch: async (workingResult, batch) => {
|
|
139
111
|
const responses = await __classPrivateFieldGet(this, _BalanceFetcher_multicallClient, "f").batchBalanceOf(chainId, batch);
|
|
140
|
-
return __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_processBalanceResponses).call(this, responses, workingResult, chainId, accountId, timestamp,
|
|
112
|
+
return __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_processBalanceResponses).call(this, responses, workingResult, chainId, accountId, timestamp, entryByAddress);
|
|
141
113
|
},
|
|
142
114
|
});
|
|
143
115
|
return {
|
|
@@ -150,37 +122,76 @@ class BalanceFetcher extends (0, polling_controller_1.StaticIntervalPollingContr
|
|
|
150
122
|
}
|
|
151
123
|
}
|
|
152
124
|
exports.BalanceFetcher = BalanceFetcher;
|
|
153
|
-
_BalanceFetcher_multicallClient = new WeakMap(), _BalanceFetcher_messenger = new WeakMap(), _BalanceFetcher_config = new WeakMap(), _BalanceFetcher_onBalanceUpdate = new WeakMap(), _BalanceFetcher_instances = new WeakSet(),
|
|
125
|
+
_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) {
|
|
126
|
+
const state = __classPrivateFieldGet(this, _BalanceFetcher_messenger, "f").call('AssetsController:getState');
|
|
127
|
+
const accountBalances = state?.assetsBalance?.[accountId];
|
|
128
|
+
if (!accountBalances) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
// Convert hex chainId to decimal for CAIP-2 matching
|
|
132
|
+
// This is safe because we are filtring with an accountId that is for evm balances only
|
|
133
|
+
const chainIdDecimal = parseInt(chainId, 16).toString();
|
|
134
|
+
const assetsToFetch = new Map();
|
|
135
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
136
|
+
const { chain: { reference: chainReference }, assetNamespace, assetReference, } = (0, utils_1.parseCaipAssetType)(assetId);
|
|
137
|
+
if (chainReference === chainIdDecimal) {
|
|
138
|
+
const assetIdLowerCase = assetId.toLowerCase();
|
|
139
|
+
if (assetsToFetch.has(assetIdLowerCase)) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const isNative = assetNamespace === 'slip44';
|
|
143
|
+
const tokenAddress = isNative
|
|
144
|
+
? constants_1.ZERO_ADDRESS
|
|
145
|
+
: assetReference.toLowerCase();
|
|
146
|
+
assetsToFetch.set(assetIdLowerCase, {
|
|
147
|
+
assetId,
|
|
148
|
+
address: tokenAddress,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return Array.from(assetsToFetch.values());
|
|
153
|
+
}, _BalanceFetcher_fetchBalances =
|
|
154
|
+
/**
|
|
155
|
+
* Fetch balances for assets already tracked in state for the given
|
|
156
|
+
* account and chain.
|
|
157
|
+
*
|
|
158
|
+
* @param chainId - Hex chain ID.
|
|
159
|
+
* @param accountId - Account UUID.
|
|
160
|
+
* @param accountAddress - On-chain address of the account.
|
|
161
|
+
* @returns Balance fetch result.
|
|
162
|
+
*/
|
|
163
|
+
async function _BalanceFetcher_fetchBalances(chainId, accountId, accountAddress) {
|
|
164
|
+
const assets = __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_getAssetsToFetch).call(this, chainId, accountId);
|
|
165
|
+
return this.fetchBalancesForAssets(chainId, accountId, accountAddress, assets);
|
|
166
|
+
}, _BalanceFetcher_processBalanceResponses = function _BalanceFetcher_processBalanceResponses(responses, accumulator, chainId, accountId, timestamp, entryByAddress) {
|
|
154
167
|
const { balances, failedAddresses } = accumulator;
|
|
155
168
|
for (const response of responses) {
|
|
156
169
|
if (!response.success) {
|
|
157
170
|
failedAddresses.push(response.tokenAddress);
|
|
158
171
|
continue;
|
|
159
172
|
}
|
|
173
|
+
const lowerAddress = response.tokenAddress.toLowerCase();
|
|
174
|
+
const entry = entryByAddress.get(lowerAddress);
|
|
175
|
+
if (!entry) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
160
178
|
const balance = response.balance ?? '0';
|
|
161
|
-
const
|
|
162
|
-
const isNative = response.tokenAddress.toLowerCase() === ZERO_ADDRESS.toLowerCase();
|
|
163
|
-
const tokenInfo = tokenInfoMap.get(response.tokenAddress.toLowerCase());
|
|
164
|
-
// Native uses 18. ERC-20: format when decimals are known; otherwise pass raw
|
|
165
|
-
// `balance` through so RpcDataSource can resolve decimals (state → list → RPC).
|
|
179
|
+
const isNative = lowerAddress === constants_1.ZERO_ADDRESS.toLowerCase();
|
|
166
180
|
let decimals;
|
|
167
181
|
let formattedBalance;
|
|
168
182
|
if (isNative) {
|
|
169
183
|
decimals = 18;
|
|
170
184
|
formattedBalance = __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_formatBalance).call(this, balance, decimals);
|
|
171
185
|
}
|
|
172
|
-
else if (
|
|
186
|
+
else if (entry.decimals === undefined) {
|
|
173
187
|
formattedBalance = balance;
|
|
174
188
|
}
|
|
175
189
|
else {
|
|
176
|
-
decimals =
|
|
190
|
+
decimals = entry.decimals;
|
|
177
191
|
formattedBalance = __classPrivateFieldGet(this, _BalanceFetcher_instances, "m", _BalanceFetcher_formatBalance).call(this, balance, decimals);
|
|
178
192
|
}
|
|
179
|
-
const assetId = isNative
|
|
180
|
-
? `eip155:${chainIdDecimal}/slip44:60`
|
|
181
|
-
: `eip155:${chainIdDecimal}/erc20:${response.tokenAddress.toLowerCase()}`;
|
|
182
193
|
const balanceEntry = {
|
|
183
|
-
assetId,
|
|
194
|
+
assetId: entry.assetId,
|
|
184
195
|
accountId,
|
|
185
196
|
chainId,
|
|
186
197
|
balance,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BalanceFetcher.cjs","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.cjs","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,5 +1,5 @@
|
|
|
1
1
|
import type { MulticallClient } from "../clients/index.cjs";
|
|
2
|
-
import type { AccountId, Address,
|
|
2
|
+
import type { AccountId, Address, AssetFetchEntry, AssetsBalanceState, BalanceFetchResult, ChainId } from "../types/index.cjs";
|
|
3
3
|
/**
|
|
4
4
|
* Minimal messenger interface for BalanceFetcher.
|
|
5
5
|
*/
|
|
@@ -9,7 +9,6 @@ export type BalanceFetcherMessenger = {
|
|
|
9
9
|
export type BalanceFetcherConfig = {
|
|
10
10
|
defaultBatchSize?: number;
|
|
11
11
|
defaultTimeoutMs?: number;
|
|
12
|
-
includeNativeByDefault?: boolean;
|
|
13
12
|
/** Polling interval in ms (default: 30s) */
|
|
14
13
|
pollingInterval?: number;
|
|
15
14
|
};
|
|
@@ -40,9 +39,7 @@ declare const BalanceFetcher_base: (abstract new (...args: any[]) => {
|
|
|
40
39
|
_executePoll(input: BalancePollingInput): Promise<void>;
|
|
41
40
|
startPolling(input: BalancePollingInput): string;
|
|
42
41
|
stopAllPolling(): void;
|
|
43
|
-
stopPollingByPollingToken(pollingToken: string): void;
|
|
44
|
-
* Polling input for BalanceFetcher - identifies what to poll for.
|
|
45
|
-
*/
|
|
42
|
+
stopPollingByPollingToken(pollingToken: string): void;
|
|
46
43
|
onPollingComplete(input: BalancePollingInput, callback: (input: BalancePollingInput) => void): void;
|
|
47
44
|
}) & {
|
|
48
45
|
new (): {};
|
|
@@ -50,6 +47,11 @@ declare const BalanceFetcher_base: (abstract new (...args: any[]) => {
|
|
|
50
47
|
/**
|
|
51
48
|
* BalanceFetcher - Fetches token balances via multicall.
|
|
52
49
|
* Extends StaticIntervalPollingControllerOnly for built-in polling support.
|
|
50
|
+
*
|
|
51
|
+
* Callers provide CAIP-19 asset IDs; the fetcher extracts on-chain addresses
|
|
52
|
+
* (or uses the zero address for native assets) and maps multicall responses
|
|
53
|
+
* back to the original asset IDs. This ensures the returned balance entries
|
|
54
|
+
* always carry the correct identifier regardless of chain.
|
|
53
55
|
*/
|
|
54
56
|
export declare class BalanceFetcher extends BalanceFetcher_base {
|
|
55
57
|
#private;
|
|
@@ -67,9 +69,19 @@ export declare class BalanceFetcher extends BalanceFetcher_base {
|
|
|
67
69
|
* @param input - The polling input.
|
|
68
70
|
*/
|
|
69
71
|
_executePoll(input: BalancePollingInput): Promise<void>;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Fetch balances for the given assets via multicall.
|
|
74
|
+
*
|
|
75
|
+
* Each entry bundles a CAIP-19 asset ID with its on-chain address and
|
|
76
|
+
* optional decimals.
|
|
77
|
+
*
|
|
78
|
+
* @param chainId - Hex chain ID.
|
|
79
|
+
* @param accountId - Account UUID.
|
|
80
|
+
* @param accountAddress - On-chain address of the account.
|
|
81
|
+
* @param assets - Asset fetch entries to fetch balances for.
|
|
82
|
+
* @returns Balance fetch result.
|
|
83
|
+
*/
|
|
84
|
+
fetchBalancesForAssets(chainId: ChainId, accountId: AccountId, accountAddress: Address, assets: AssetFetchEntry[]): Promise<BalanceFetchResult>;
|
|
73
85
|
}
|
|
74
86
|
export {};
|
|
75
87
|
//# sourceMappingURL=BalanceFetcher.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BalanceFetcher.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/BalanceFetcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BalanceFetcher.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/BalanceFetcher.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,6BAAmB;AAClD,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAEP,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAIlB,OAAO,EACR,2BAAiB;AAKlB;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,CAAC,MAAM,EAAE,2BAA2B,KAAK,kBAAkB,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,CACpC,MAAM,EAAE,kBAAkB,KACvB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;;;;;;;;;;;;;;;;;;AAE1B;;;;;;;;GAQG;AACH,qBAAa,cAAe,SAAQ,mBAA0D;;gBAU1F,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,uBAAuB,EAClC,MAAM,CAAC,EAAE,oBAAoB;IAc/B;;;;OAIG;IACH,kBAAkB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,IAAI;IAI3D;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsF7D;;;;;;;;;;;OAWG;IACG,sBAAsB,CAC1B,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,MAAM,EAAE,eAAe,EAAE,GACxB,OAAO,CAAC,kBAAkB,CAAC;CAyJ/B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MulticallClient } from "../clients/index.mjs";
|
|
2
|
-
import type { AccountId, Address,
|
|
2
|
+
import type { AccountId, Address, AssetFetchEntry, AssetsBalanceState, BalanceFetchResult, ChainId } from "../types/index.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* Minimal messenger interface for BalanceFetcher.
|
|
5
5
|
*/
|
|
@@ -9,7 +9,6 @@ export type BalanceFetcherMessenger = {
|
|
|
9
9
|
export type BalanceFetcherConfig = {
|
|
10
10
|
defaultBatchSize?: number;
|
|
11
11
|
defaultTimeoutMs?: number;
|
|
12
|
-
includeNativeByDefault?: boolean;
|
|
13
12
|
/** Polling interval in ms (default: 30s) */
|
|
14
13
|
pollingInterval?: number;
|
|
15
14
|
};
|
|
@@ -40,9 +39,7 @@ declare const BalanceFetcher_base: (abstract new (...args: any[]) => {
|
|
|
40
39
|
_executePoll(input: BalancePollingInput): Promise<void>;
|
|
41
40
|
startPolling(input: BalancePollingInput): string;
|
|
42
41
|
stopAllPolling(): void;
|
|
43
|
-
stopPollingByPollingToken(pollingToken: string): void;
|
|
44
|
-
* Polling input for BalanceFetcher - identifies what to poll for.
|
|
45
|
-
*/
|
|
42
|
+
stopPollingByPollingToken(pollingToken: string): void;
|
|
46
43
|
onPollingComplete(input: BalancePollingInput, callback: (input: BalancePollingInput) => void): void;
|
|
47
44
|
}) & {
|
|
48
45
|
new (): {};
|
|
@@ -50,6 +47,11 @@ declare const BalanceFetcher_base: (abstract new (...args: any[]) => {
|
|
|
50
47
|
/**
|
|
51
48
|
* BalanceFetcher - Fetches token balances via multicall.
|
|
52
49
|
* Extends StaticIntervalPollingControllerOnly for built-in polling support.
|
|
50
|
+
*
|
|
51
|
+
* Callers provide CAIP-19 asset IDs; the fetcher extracts on-chain addresses
|
|
52
|
+
* (or uses the zero address for native assets) and maps multicall responses
|
|
53
|
+
* back to the original asset IDs. This ensures the returned balance entries
|
|
54
|
+
* always carry the correct identifier regardless of chain.
|
|
53
55
|
*/
|
|
54
56
|
export declare class BalanceFetcher extends BalanceFetcher_base {
|
|
55
57
|
#private;
|
|
@@ -67,9 +69,19 @@ export declare class BalanceFetcher extends BalanceFetcher_base {
|
|
|
67
69
|
* @param input - The polling input.
|
|
68
70
|
*/
|
|
69
71
|
_executePoll(input: BalancePollingInput): Promise<void>;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Fetch balances for the given assets via multicall.
|
|
74
|
+
*
|
|
75
|
+
* Each entry bundles a CAIP-19 asset ID with its on-chain address and
|
|
76
|
+
* optional decimals.
|
|
77
|
+
*
|
|
78
|
+
* @param chainId - Hex chain ID.
|
|
79
|
+
* @param accountId - Account UUID.
|
|
80
|
+
* @param accountAddress - On-chain address of the account.
|
|
81
|
+
* @param assets - Asset fetch entries to fetch balances for.
|
|
82
|
+
* @returns Balance fetch result.
|
|
83
|
+
*/
|
|
84
|
+
fetchBalancesForAssets(chainId: ChainId, accountId: AccountId, accountAddress: Address, assets: AssetFetchEntry[]): Promise<BalanceFetchResult>;
|
|
73
85
|
}
|
|
74
86
|
export {};
|
|
75
87
|
//# sourceMappingURL=BalanceFetcher.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BalanceFetcher.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/BalanceFetcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BalanceFetcher.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/BalanceFetcher.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,6BAAmB;AAClD,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAEP,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAIlB,OAAO,EACR,2BAAiB;AAKlB;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,CAAC,MAAM,EAAE,2BAA2B,KAAK,kBAAkB,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,CACpC,MAAM,EAAE,kBAAkB,KACvB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;;;;;;;;;;;;;;;;;;AAE1B;;;;;;;;GAQG;AACH,qBAAa,cAAe,SAAQ,mBAA0D;;gBAU1F,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,uBAAuB,EAClC,MAAM,CAAC,EAAE,oBAAoB;IAc/B;;;;OAIG;IACH,kBAAkB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,IAAI;IAI3D;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsF7D;;;;;;;;;;;OAWG;IACG,sBAAsB,CAC1B,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,MAAM,EAAE,eAAe,EAAE,GACxB,OAAO,CAAC,kBAAkB,CAAC;CAyJ/B"}
|