@metamask/assets-controllers 74.0.0 → 74.1.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 +37 -1
- package/dist/AccountTrackerController.cjs +214 -84
- package/dist/AccountTrackerController.cjs.map +1 -1
- package/dist/AccountTrackerController.d.cts +7 -1
- package/dist/AccountTrackerController.d.cts.map +1 -1
- package/dist/AccountTrackerController.d.mts +7 -1
- package/dist/AccountTrackerController.d.mts.map +1 -1
- package/dist/AccountTrackerController.mjs +216 -85
- package/dist/AccountTrackerController.mjs.map +1 -1
- package/dist/TokenBalancesController.cjs +14 -9
- package/dist/TokenBalancesController.cjs.map +1 -1
- package/dist/TokenBalancesController.d.cts.map +1 -1
- package/dist/TokenBalancesController.d.mts.map +1 -1
- package/dist/TokenBalancesController.mjs +15 -10
- package/dist/TokenBalancesController.mjs.map +1 -1
- package/dist/multicall.cjs +1 -1
- package/dist/multicall.cjs.map +1 -1
- package/dist/multicall.mjs +1 -1
- package/dist/multicall.mjs.map +1 -1
- package/dist/selectors/token-selectors.cjs +24 -9
- package/dist/selectors/token-selectors.cjs.map +1 -1
- package/dist/selectors/token-selectors.d.cts +96 -20
- package/dist/selectors/token-selectors.d.cts.map +1 -1
- package/dist/selectors/token-selectors.d.mts +96 -20
- package/dist/selectors/token-selectors.d.mts.map +1 -1
- package/dist/selectors/token-selectors.mjs +24 -9
- package/dist/selectors/token-selectors.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -8,6 +8,8 @@ import { type AssetsContractController, type StakedBalance } from "./AssetsContr
|
|
|
8
8
|
* The name of the {@link AccountTrackerController}.
|
|
9
9
|
*/
|
|
10
10
|
declare const controllerName = "AccountTrackerController";
|
|
11
|
+
export type ChainIdHex = Hex;
|
|
12
|
+
export type ChecksumAddress = Hex;
|
|
11
13
|
/**
|
|
12
14
|
* AccountInformation
|
|
13
15
|
*
|
|
@@ -108,13 +110,17 @@ export declare class AccountTrackerController extends AccountTrackerController_b
|
|
|
108
110
|
* @param options.messenger - The controller messaging system.
|
|
109
111
|
* @param options.getStakedBalanceForChain - The function to get the staked native asset balance for a chain.
|
|
110
112
|
* @param options.includeStakedAssets - Whether to include staked assets in the account balances.
|
|
113
|
+
* @param options.useAccountsAPI - Enable Accounts‑API strategy (if supported chain).
|
|
114
|
+
* @param options.allowExternalServices - Disable external HTTP calls (privacy / offline mode).
|
|
111
115
|
*/
|
|
112
|
-
constructor({ interval, state, messenger, getStakedBalanceForChain, includeStakedAssets, }: {
|
|
116
|
+
constructor({ interval, state, messenger, getStakedBalanceForChain, includeStakedAssets, useAccountsAPI, allowExternalServices, }: {
|
|
113
117
|
interval?: number;
|
|
114
118
|
state?: Partial<AccountTrackerControllerState>;
|
|
115
119
|
messenger: AccountTrackerControllerMessenger;
|
|
116
120
|
getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];
|
|
117
121
|
includeStakedAssets?: boolean;
|
|
122
|
+
useAccountsAPI?: boolean;
|
|
123
|
+
allowExternalServices?: () => boolean;
|
|
118
124
|
});
|
|
119
125
|
private syncAccounts;
|
|
120
126
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTrackerController.d.cts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,+CAA+C,EAC/C,0CAA0C,EAC1C,oCAAoC,EACpC,4CAA4C,EAC7C,sCAAsC;AACvC,OAAO,KAAK,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACpB,kCAAkC;AAOnC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"AccountTrackerController.d.cts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ import { type AssetsContractController, type StakedBalance } from "./AssetsContr
|
|
|
8
8
|
* The name of the {@link AccountTrackerController}.
|
|
9
9
|
*/
|
|
10
10
|
declare const controllerName = "AccountTrackerController";
|
|
11
|
+
export type ChainIdHex = Hex;
|
|
12
|
+
export type ChecksumAddress = Hex;
|
|
11
13
|
/**
|
|
12
14
|
* AccountInformation
|
|
13
15
|
*
|
|
@@ -108,13 +110,17 @@ export declare class AccountTrackerController extends AccountTrackerController_b
|
|
|
108
110
|
* @param options.messenger - The controller messaging system.
|
|
109
111
|
* @param options.getStakedBalanceForChain - The function to get the staked native asset balance for a chain.
|
|
110
112
|
* @param options.includeStakedAssets - Whether to include staked assets in the account balances.
|
|
113
|
+
* @param options.useAccountsAPI - Enable Accounts‑API strategy (if supported chain).
|
|
114
|
+
* @param options.allowExternalServices - Disable external HTTP calls (privacy / offline mode).
|
|
111
115
|
*/
|
|
112
|
-
constructor({ interval, state, messenger, getStakedBalanceForChain, includeStakedAssets, }: {
|
|
116
|
+
constructor({ interval, state, messenger, getStakedBalanceForChain, includeStakedAssets, useAccountsAPI, allowExternalServices, }: {
|
|
113
117
|
interval?: number;
|
|
114
118
|
state?: Partial<AccountTrackerControllerState>;
|
|
115
119
|
messenger: AccountTrackerControllerMessenger;
|
|
116
120
|
getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];
|
|
117
121
|
includeStakedAssets?: boolean;
|
|
122
|
+
useAccountsAPI?: boolean;
|
|
123
|
+
allowExternalServices?: () => boolean;
|
|
118
124
|
});
|
|
119
125
|
private syncAccounts;
|
|
120
126
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTrackerController.d.mts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,+CAA+C,EAC/C,0CAA0C,EAC1C,oCAAoC,EACpC,4CAA4C,EAC7C,sCAAsC;AACvC,OAAO,KAAK,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACpB,kCAAkC;AAOnC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"AccountTrackerController.d.mts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ 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 _AccountTrackerController_instances, _AccountTrackerController_refreshMutex, _AccountTrackerController_includeStakedAssets, _AccountTrackerController_getStakedBalanceForChain, _AccountTrackerController_getCorrectNetworkClient, _AccountTrackerController_getNetworkClientIds,
|
|
12
|
+
var _AccountTrackerRpcBalanceFetcher_instances, _AccountTrackerRpcBalanceFetcher_getProvider, _AccountTrackerRpcBalanceFetcher_getNetworkClient, _AccountTrackerRpcBalanceFetcher_includeStakedAssets, _AccountTrackerRpcBalanceFetcher_getStakedBalanceForChain, _AccountTrackerRpcBalanceFetcher_getBalanceFromChain, _AccountTrackerController_instances, _AccountTrackerController_refreshMutex, _AccountTrackerController_includeStakedAssets, _AccountTrackerController_getStakedBalanceForChain, _AccountTrackerController_balanceFetchers, _AccountTrackerController_getProvider, _AccountTrackerController_getNetworkClient, _AccountTrackerController_getCorrectNetworkClient, _AccountTrackerController_getNetworkClientIds, _AccountTrackerController_registerMessageHandlers;
|
|
13
13
|
function $importDefault(module) {
|
|
14
14
|
if (module?.__esModule) {
|
|
15
15
|
return module.default;
|
|
@@ -24,16 +24,139 @@ const EthQuery = $importDefault($EthQuery);
|
|
|
24
24
|
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
|
25
25
|
import { assert, hasProperty } from "@metamask/utils";
|
|
26
26
|
import { Mutex } from "async-mutex";
|
|
27
|
+
import $BN from "bn.js";
|
|
28
|
+
const BN = $importDefault($BN);
|
|
27
29
|
import $lodash from "lodash";
|
|
28
30
|
const { cloneDeep, isEqual } = $lodash;
|
|
29
31
|
import $abiSingleCallBalancesContract from "single-call-balance-checker-abi";
|
|
30
32
|
const abiSingleCallBalancesContract = $importDefault($abiSingleCallBalancesContract);
|
|
31
|
-
import { SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID } from "./AssetsContractController.mjs";
|
|
33
|
+
import { SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID, STAKING_CONTRACT_ADDRESS_BY_CHAINID } from "./AssetsContractController.mjs";
|
|
32
34
|
import { reduceInBatchesSerially, TOKEN_PRICES_BATCH_SIZE } from "./assetsUtil.mjs";
|
|
35
|
+
import { AccountsApiBalanceFetcher } from "./multi-chain-accounts-service/api-balance-fetcher.mjs";
|
|
33
36
|
/**
|
|
34
37
|
* The name of the {@link AccountTrackerController}.
|
|
35
38
|
*/
|
|
36
39
|
const controllerName = 'AccountTrackerController';
|
|
40
|
+
const DEFAULT_TIMEOUT_MS = 15000;
|
|
41
|
+
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
42
|
+
/**
|
|
43
|
+
* RPC-based balance fetcher for AccountTrackerController.
|
|
44
|
+
* Fetches only native balances and staked balances (no token balances).
|
|
45
|
+
*/
|
|
46
|
+
class AccountTrackerRpcBalanceFetcher {
|
|
47
|
+
constructor(getProvider, getNetworkClient, includeStakedAssets, getStakedBalanceForChain) {
|
|
48
|
+
_AccountTrackerRpcBalanceFetcher_instances.add(this);
|
|
49
|
+
_AccountTrackerRpcBalanceFetcher_getProvider.set(this, void 0);
|
|
50
|
+
_AccountTrackerRpcBalanceFetcher_getNetworkClient.set(this, void 0);
|
|
51
|
+
_AccountTrackerRpcBalanceFetcher_includeStakedAssets.set(this, void 0);
|
|
52
|
+
_AccountTrackerRpcBalanceFetcher_getStakedBalanceForChain.set(this, void 0);
|
|
53
|
+
__classPrivateFieldSet(this, _AccountTrackerRpcBalanceFetcher_getProvider, getProvider, "f");
|
|
54
|
+
__classPrivateFieldSet(this, _AccountTrackerRpcBalanceFetcher_getNetworkClient, getNetworkClient, "f");
|
|
55
|
+
__classPrivateFieldSet(this, _AccountTrackerRpcBalanceFetcher_includeStakedAssets, includeStakedAssets, "f");
|
|
56
|
+
__classPrivateFieldSet(this, _AccountTrackerRpcBalanceFetcher_getStakedBalanceForChain, getStakedBalanceForChain, "f");
|
|
57
|
+
}
|
|
58
|
+
supports() {
|
|
59
|
+
return true; // fallback – supports every chain
|
|
60
|
+
}
|
|
61
|
+
async fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }) {
|
|
62
|
+
const results = [];
|
|
63
|
+
for (const chainId of chainIds) {
|
|
64
|
+
const accountsToUpdate = queryAllAccounts
|
|
65
|
+
? Object.values(allAccounts).map((account) => toChecksumHexAddress(account.address))
|
|
66
|
+
: [selectedAccount];
|
|
67
|
+
const { provider, blockTracker } = __classPrivateFieldGet(this, _AccountTrackerRpcBalanceFetcher_getNetworkClient, "f").call(this, chainId);
|
|
68
|
+
const ethQuery = new EthQuery(provider);
|
|
69
|
+
// Force fresh block data before multicall
|
|
70
|
+
await safelyExecuteWithTimeout(() => blockTracker?.checkForLatestBlock?.());
|
|
71
|
+
// Fetch native balances
|
|
72
|
+
if (hasProperty(SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID, chainId)) {
|
|
73
|
+
const contractAddress = SINGLE_CALL_BALANCES_ADDRESS_BY_CHAINID[chainId];
|
|
74
|
+
const contract = new Contract(contractAddress, abiSingleCallBalancesContract, __classPrivateFieldGet(this, _AccountTrackerRpcBalanceFetcher_getProvider, "f").call(this, chainId));
|
|
75
|
+
const nativeBalances = await safelyExecuteWithTimeout(() => contract.balances(accountsToUpdate, [ZERO_ADDRESS]), false, 3000);
|
|
76
|
+
if (nativeBalances) {
|
|
77
|
+
accountsToUpdate.forEach((address, index) => {
|
|
78
|
+
results.push({
|
|
79
|
+
success: true,
|
|
80
|
+
value: new BN(nativeBalances[index].toString()),
|
|
81
|
+
account: address,
|
|
82
|
+
token: ZERO_ADDRESS,
|
|
83
|
+
chainId,
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Process accounts in batches using reduceInBatchesSerially
|
|
90
|
+
await reduceInBatchesSerially({
|
|
91
|
+
values: accountsToUpdate,
|
|
92
|
+
batchSize: TOKEN_PRICES_BATCH_SIZE,
|
|
93
|
+
initialResult: undefined,
|
|
94
|
+
eachBatch: async (workingResult, batch) => {
|
|
95
|
+
const balancePromises = batch.map(async (address) => {
|
|
96
|
+
const balanceResult = await __classPrivateFieldGet(this, _AccountTrackerRpcBalanceFetcher_instances, "m", _AccountTrackerRpcBalanceFetcher_getBalanceFromChain).call(this, address, ethQuery).catch(() => null);
|
|
97
|
+
if (balanceResult) {
|
|
98
|
+
results.push({
|
|
99
|
+
success: true,
|
|
100
|
+
value: new BN(balanceResult.replace('0x', ''), 16),
|
|
101
|
+
account: address,
|
|
102
|
+
token: ZERO_ADDRESS,
|
|
103
|
+
chainId,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
results.push({
|
|
108
|
+
success: false,
|
|
109
|
+
account: address,
|
|
110
|
+
token: ZERO_ADDRESS,
|
|
111
|
+
chainId,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
await Promise.allSettled(balancePromises);
|
|
116
|
+
return workingResult;
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// Fetch staked balances if enabled
|
|
121
|
+
if (__classPrivateFieldGet(this, _AccountTrackerRpcBalanceFetcher_includeStakedAssets, "f")) {
|
|
122
|
+
const stakedBalancesPromise = __classPrivateFieldGet(this, _AccountTrackerRpcBalanceFetcher_getStakedBalanceForChain, "f").call(this, accountsToUpdate, chainId);
|
|
123
|
+
const stakedBalanceResult = await safelyExecuteWithTimeout(async () => (await stakedBalancesPromise));
|
|
124
|
+
if (stakedBalanceResult) {
|
|
125
|
+
// Find the staking contract address for this chain
|
|
126
|
+
const stakingContractAddress = STAKING_CONTRACT_ADDRESS_BY_CHAINID[chainId];
|
|
127
|
+
if (stakingContractAddress) {
|
|
128
|
+
Object.entries(stakedBalanceResult).forEach(([address, balance]) => {
|
|
129
|
+
results.push({
|
|
130
|
+
success: true,
|
|
131
|
+
value: balance
|
|
132
|
+
? new BN(balance.replace('0x', ''), 16)
|
|
133
|
+
: new BN('0'),
|
|
134
|
+
account: address,
|
|
135
|
+
token: toChecksumHexAddress(stakingContractAddress),
|
|
136
|
+
chainId,
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return results;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
_AccountTrackerRpcBalanceFetcher_getProvider = new WeakMap(), _AccountTrackerRpcBalanceFetcher_getNetworkClient = new WeakMap(), _AccountTrackerRpcBalanceFetcher_includeStakedAssets = new WeakMap(), _AccountTrackerRpcBalanceFetcher_getStakedBalanceForChain = new WeakMap(), _AccountTrackerRpcBalanceFetcher_instances = new WeakSet(), _AccountTrackerRpcBalanceFetcher_getBalanceFromChain =
|
|
147
|
+
/**
|
|
148
|
+
* Fetches the balance of a given address from the blockchain.
|
|
149
|
+
*
|
|
150
|
+
* @param address - The account address to fetch the balance for.
|
|
151
|
+
* @param ethQuery - The EthQuery instance to query getBalance with.
|
|
152
|
+
* @returns A promise that resolves to the balance in a hex string format.
|
|
153
|
+
*/
|
|
154
|
+
async function _AccountTrackerRpcBalanceFetcher_getBalanceFromChain(address, ethQuery) {
|
|
155
|
+
return await safelyExecuteWithTimeout(async () => {
|
|
156
|
+
assert(ethQuery, 'Provider not set.');
|
|
157
|
+
return await query(ethQuery, 'getBalance', [address]);
|
|
158
|
+
});
|
|
159
|
+
};
|
|
37
160
|
const accountTrackerMetadata = {
|
|
38
161
|
accountsByChainId: {
|
|
39
162
|
persist: true,
|
|
@@ -53,8 +176,10 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
53
176
|
* @param options.messenger - The controller messaging system.
|
|
54
177
|
* @param options.getStakedBalanceForChain - The function to get the staked native asset balance for a chain.
|
|
55
178
|
* @param options.includeStakedAssets - Whether to include staked assets in the account balances.
|
|
179
|
+
* @param options.useAccountsAPI - Enable Accounts‑API strategy (if supported chain).
|
|
180
|
+
* @param options.allowExternalServices - Disable external HTTP calls (privacy / offline mode).
|
|
56
181
|
*/
|
|
57
|
-
constructor({ interval = 10000, state, messenger, getStakedBalanceForChain, includeStakedAssets = false, }) {
|
|
182
|
+
constructor({ interval = 10000, state, messenger, getStakedBalanceForChain, includeStakedAssets = false, useAccountsAPI = false, allowExternalServices = () => true, }) {
|
|
58
183
|
const { selectedNetworkClientId } = messenger.call('NetworkController:getState');
|
|
59
184
|
const { configuration: { chainId }, } = messenger.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
|
|
60
185
|
super({
|
|
@@ -72,8 +197,29 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
72
197
|
_AccountTrackerController_refreshMutex.set(this, new Mutex());
|
|
73
198
|
_AccountTrackerController_includeStakedAssets.set(this, void 0);
|
|
74
199
|
_AccountTrackerController_getStakedBalanceForChain.set(this, void 0);
|
|
200
|
+
_AccountTrackerController_balanceFetchers.set(this, void 0);
|
|
201
|
+
_AccountTrackerController_getProvider.set(this, (chainId) => {
|
|
202
|
+
const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
|
|
203
|
+
const cfg = networkConfigurationsByChainId[chainId];
|
|
204
|
+
const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];
|
|
205
|
+
const client = this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientId);
|
|
206
|
+
return new Web3Provider(client.provider);
|
|
207
|
+
});
|
|
208
|
+
_AccountTrackerController_getNetworkClient.set(this, (chainId) => {
|
|
209
|
+
const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
|
|
210
|
+
const cfg = networkConfigurationsByChainId[chainId];
|
|
211
|
+
const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];
|
|
212
|
+
return this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientId);
|
|
213
|
+
});
|
|
75
214
|
__classPrivateFieldSet(this, _AccountTrackerController_getStakedBalanceForChain, getStakedBalanceForChain, "f");
|
|
76
215
|
__classPrivateFieldSet(this, _AccountTrackerController_includeStakedAssets, includeStakedAssets, "f");
|
|
216
|
+
// Initialize balance fetchers - Strategy order: API first, then RPC fallback
|
|
217
|
+
__classPrivateFieldSet(this, _AccountTrackerController_balanceFetchers, [
|
|
218
|
+
...(useAccountsAPI && allowExternalServices()
|
|
219
|
+
? [new AccountsApiBalanceFetcher('extension', __classPrivateFieldGet(this, _AccountTrackerController_getProvider, "f"))]
|
|
220
|
+
: []),
|
|
221
|
+
new AccountTrackerRpcBalanceFetcher(__classPrivateFieldGet(this, _AccountTrackerController_getProvider, "f"), __classPrivateFieldGet(this, _AccountTrackerController_getNetworkClient, "f"), includeStakedAssets, getStakedBalanceForChain),
|
|
222
|
+
], "f");
|
|
77
223
|
this.setIntervalLength(interval);
|
|
78
224
|
this.messagingSystem.subscribe('AccountsController:selectedEvmAccountChange', (newAddress, prevAddress) => {
|
|
79
225
|
if (newAddress !== prevAddress) {
|
|
@@ -143,6 +289,8 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
143
289
|
*/
|
|
144
290
|
async refresh(networkClientIds) {
|
|
145
291
|
const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
|
|
292
|
+
const allAccounts = this.messagingSystem.call('AccountsController:listAccounts');
|
|
293
|
+
const { isMultiAccountBalancesEnabled } = this.messagingSystem.call('PreferencesController:getState');
|
|
146
294
|
const releaseLock = await __classPrivateFieldGet(this, _AccountTrackerController_refreshMutex, "f").acquire();
|
|
147
295
|
try {
|
|
148
296
|
const chainIds = networkClientIds.map((networkClientId) => {
|
|
@@ -150,83 +298,79 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
150
298
|
return chainId;
|
|
151
299
|
});
|
|
152
300
|
this.syncAccounts(chainIds);
|
|
153
|
-
//
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
};
|
|
180
|
-
});
|
|
301
|
+
// Use balance fetchers with fallback strategy
|
|
302
|
+
const aggregated = [];
|
|
303
|
+
let remainingChains = [...chainIds];
|
|
304
|
+
// Try each fetcher in order, removing successfully processed chains
|
|
305
|
+
for (const fetcher of __classPrivateFieldGet(this, _AccountTrackerController_balanceFetchers, "f")) {
|
|
306
|
+
const supportedChains = remainingChains.filter((c) => fetcher.supports(c));
|
|
307
|
+
if (!supportedChains.length) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
const balances = await Promise.race([
|
|
312
|
+
fetcher.fetch({
|
|
313
|
+
chainIds: supportedChains,
|
|
314
|
+
queryAllAccounts: isMultiAccountBalancesEnabled,
|
|
315
|
+
selectedAccount: toChecksumHexAddress(selectedAccount.address),
|
|
316
|
+
allAccounts,
|
|
317
|
+
}),
|
|
318
|
+
new Promise((_resolve, reject) => setTimeout(() => {
|
|
319
|
+
reject(new Error(`Timeout after ${DEFAULT_TIMEOUT_MS}ms`));
|
|
320
|
+
}, DEFAULT_TIMEOUT_MS)),
|
|
321
|
+
]);
|
|
322
|
+
if (balances && balances.length > 0) {
|
|
323
|
+
aggregated.push(...balances);
|
|
324
|
+
// Remove chains that were successfully processed
|
|
325
|
+
const processedChains = new Set(balances.map((b) => b.chainId));
|
|
326
|
+
remainingChains = remainingChains.filter((chain) => !processedChains.has(chain));
|
|
181
327
|
}
|
|
182
328
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
values: accountsToUpdate,
|
|
187
|
-
batchSize: TOKEN_PRICES_BATCH_SIZE,
|
|
188
|
-
initialResult: undefined,
|
|
189
|
-
eachBatch: async (workingResult, batch) => {
|
|
190
|
-
const balancePromises = batch.map(async (address) => {
|
|
191
|
-
const balanceResult = await __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getBalanceFromChain).call(this, address, ethQuery).catch(() => null);
|
|
192
|
-
// Update account balances
|
|
193
|
-
if (balanceResult) {
|
|
194
|
-
accountsForChain[address] = {
|
|
195
|
-
balance: balanceResult,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
await Promise.allSettled(balancePromises);
|
|
200
|
-
return workingResult;
|
|
201
|
-
},
|
|
202
|
-
});
|
|
329
|
+
catch (error) {
|
|
330
|
+
console.warn(`Balance fetcher failed for chains ${supportedChains.join(', ')}: ${String(error)}`);
|
|
331
|
+
// Continue to next fetcher (fallback)
|
|
203
332
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
};
|
|
210
|
-
});
|
|
211
|
-
// After all batches are processed, return the updated data
|
|
212
|
-
return { chainId, accountsForChain };
|
|
213
|
-
});
|
|
214
|
-
// Wait for all networkClientId updates to settle in parallel
|
|
215
|
-
const allResults = await Promise.allSettled(updatePromises);
|
|
333
|
+
// If all chains have been processed, break early
|
|
334
|
+
if (remainingChains.length === 0) {
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
216
338
|
// Build a _copy_ of the current state and track whether anything changed
|
|
217
339
|
const nextAccountsByChainId = cloneDeep(this.state.accountsByChainId);
|
|
218
340
|
let hasChanges = false;
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
341
|
+
// Process the aggregated balance results
|
|
342
|
+
const stakedBalancesByChainAndAddress = {};
|
|
343
|
+
aggregated.forEach(({ success, value, account, token, chainId }) => {
|
|
344
|
+
if (success && value !== undefined) {
|
|
345
|
+
const hexValue = `0x${value.toString(16)}`;
|
|
346
|
+
if (token === ZERO_ADDRESS) {
|
|
347
|
+
// Native balance
|
|
348
|
+
if (nextAccountsByChainId[chainId][account].balance !== hexValue) {
|
|
349
|
+
nextAccountsByChainId[chainId][account].balance = hexValue;
|
|
350
|
+
hasChanges = true;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
// Staked balance (from staking contract address)
|
|
355
|
+
if (!stakedBalancesByChainAndAddress[chainId]) {
|
|
356
|
+
stakedBalancesByChainAndAddress[chainId] = {};
|
|
357
|
+
}
|
|
358
|
+
stakedBalancesByChainAndAddress[chainId][account] = hexValue;
|
|
226
359
|
}
|
|
227
360
|
}
|
|
228
361
|
});
|
|
229
|
-
//
|
|
362
|
+
// Apply staked balances
|
|
363
|
+
Object.entries(stakedBalancesByChainAndAddress).forEach(([chainId, balancesByAddress]) => {
|
|
364
|
+
Object.entries(balancesByAddress).forEach(([address, stakedBalance]) => {
|
|
365
|
+
if (nextAccountsByChainId[chainId][address].stakedBalance !==
|
|
366
|
+
stakedBalance) {
|
|
367
|
+
nextAccountsByChainId[chainId][address].stakedBalance =
|
|
368
|
+
stakedBalance;
|
|
369
|
+
hasChanges = true;
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
// Only update state if something changed
|
|
230
374
|
if (hasChanges) {
|
|
231
375
|
this.update((state) => {
|
|
232
376
|
state.accountsByChainId = nextAccountsByChainId;
|
|
@@ -320,7 +464,7 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
320
464
|
});
|
|
321
465
|
}
|
|
322
466
|
}
|
|
323
|
-
_AccountTrackerController_refreshMutex = new WeakMap(), _AccountTrackerController_includeStakedAssets = new WeakMap(), _AccountTrackerController_getStakedBalanceForChain = new WeakMap(), _AccountTrackerController_instances = new WeakSet(), _AccountTrackerController_getCorrectNetworkClient = function _AccountTrackerController_getCorrectNetworkClient(networkClientId) {
|
|
467
|
+
_AccountTrackerController_refreshMutex = new WeakMap(), _AccountTrackerController_includeStakedAssets = new WeakMap(), _AccountTrackerController_getStakedBalanceForChain = new WeakMap(), _AccountTrackerController_balanceFetchers = new WeakMap(), _AccountTrackerController_getProvider = new WeakMap(), _AccountTrackerController_getNetworkClient = new WeakMap(), _AccountTrackerController_instances = new WeakSet(), _AccountTrackerController_getCorrectNetworkClient = function _AccountTrackerController_getCorrectNetworkClient(networkClientId) {
|
|
324
468
|
const selectedNetworkClientId = networkClientId ??
|
|
325
469
|
this.messagingSystem.call('NetworkController:getState')
|
|
326
470
|
.selectedNetworkClientId;
|
|
@@ -334,19 +478,6 @@ _AccountTrackerController_refreshMutex = new WeakMap(), _AccountTrackerControlle
|
|
|
334
478
|
}, _AccountTrackerController_getNetworkClientIds = function _AccountTrackerController_getNetworkClientIds() {
|
|
335
479
|
const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
|
|
336
480
|
return Object.values(networkConfigurationsByChainId).flatMap((networkConfiguration) => networkConfiguration.rpcEndpoints.map((rpcEndpoint) => rpcEndpoint.networkClientId));
|
|
337
|
-
}, _AccountTrackerController_getBalanceFromChain =
|
|
338
|
-
/**
|
|
339
|
-
* Fetches the balance of a given address from the blockchain.
|
|
340
|
-
*
|
|
341
|
-
* @param address - The account address to fetch the balance for.
|
|
342
|
-
* @param ethQuery - The EthQuery instance to query getBalnce with.
|
|
343
|
-
* @returns A promise that resolves to the balance in a hex string format.
|
|
344
|
-
*/
|
|
345
|
-
async function _AccountTrackerController_getBalanceFromChain(address, ethQuery) {
|
|
346
|
-
return await safelyExecuteWithTimeout(async () => {
|
|
347
|
-
assert(ethQuery, 'Provider not set.');
|
|
348
|
-
return await query(ethQuery, 'getBalance', [address]);
|
|
349
|
-
});
|
|
350
481
|
}, _AccountTrackerController_registerMessageHandlers = function _AccountTrackerController_registerMessageHandlers() {
|
|
351
482
|
this.messagingSystem.registerActionHandler(`${controllerName}:updateNativeBalances`, this.updateNativeBalances.bind(this));
|
|
352
483
|
this.messagingSystem.registerActionHandler(`${controllerName}:updateStakedBalances`, this.updateStakedBalances.bind(this));
|