@metamask-previews/assets-controller 0.0.0-preview-dcbbb24 → 0.0.0-preview-57408350
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-sources/SnapDataSource.cjs +193 -464
- package/dist/data-sources/SnapDataSource.cjs.map +1 -1
- package/dist/data-sources/SnapDataSource.d.cts +24 -86
- package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
- package/dist/data-sources/SnapDataSource.d.mts +24 -86
- package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
- package/dist/data-sources/SnapDataSource.mjs +191 -458
- package/dist/data-sources/SnapDataSource.mjs.map +1 -1
- package/dist/data-sources/index.cjs +7 -36
- package/dist/data-sources/index.cjs.map +1 -1
- package/dist/data-sources/index.d.cts +1 -1
- package/dist/data-sources/index.d.cts.map +1 -1
- package/dist/data-sources/index.d.mts +1 -1
- package/dist/data-sources/index.d.mts.map +1 -1
- package/dist/data-sources/index.mjs +5 -13
- package/dist/data-sources/index.mjs.map +1 -1
- package/dist/data-sources/initDataSources.cjs +9 -3
- package/dist/data-sources/initDataSources.cjs.map +1 -1
- package/dist/data-sources/initDataSources.d.cts +2 -4
- package/dist/data-sources/initDataSources.d.cts.map +1 -1
- package/dist/data-sources/initDataSources.d.mts +2 -4
- package/dist/data-sources/initDataSources.d.mts.map +1 -1
- package/dist/data-sources/initDataSources.mjs +9 -3
- package/dist/data-sources/initDataSources.mjs.map +1 -1
- package/dist/index.cjs +7 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -1
|
@@ -10,9 +10,11 @@ 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 _SnapDataSource_instances, _SnapDataSource_messenger,
|
|
13
|
+
var _SnapDataSource_instances, _SnapDataSource_messenger, _SnapDataSource_handleSnapBalancesUpdatedBound, _SnapDataSource_handlePermissionStateChangeBound, _SnapDataSource_keyringClientCache, _SnapDataSource_subscribeToEvents, _SnapDataSource_handleSnapBalancesUpdated, _SnapDataSource_isChainSupportedBySnap, _SnapDataSource_registerActionHandlers, _SnapDataSource_getRunnableSnaps, _SnapDataSource_getSnapPermissions, _SnapDataSource_discoverKeyringSnaps, _SnapDataSource_getKeyringClient;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.createSnapDataSource = exports.SnapDataSource = exports.
|
|
15
|
+
exports.createSnapDataSource = exports.SnapDataSource = exports.extractChainFromAssetId = exports.getChainIdsCaveat = exports.ASSETS_PERMISSION = exports.KEYRING_PERMISSION = exports.SNAP_DATA_SOURCE_NAME = void 0;
|
|
16
|
+
const keyring_snap_client_1 = require("@metamask/keyring-snap-client");
|
|
17
|
+
const snaps_utils_1 = require("@metamask/snaps-utils");
|
|
16
18
|
const AbstractDataSource_1 = require("./AbstractDataSource.cjs");
|
|
17
19
|
const logger_1 = require("../logger.cjs");
|
|
18
20
|
const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'SnapDataSource');
|
|
@@ -20,92 +22,31 @@ const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'SnapDataSo
|
|
|
20
22
|
// CONSTANTS
|
|
21
23
|
// ============================================================================
|
|
22
24
|
exports.SNAP_DATA_SOURCE_NAME = 'SnapDataSource';
|
|
23
|
-
|
|
24
|
-
exports.
|
|
25
|
-
|
|
26
|
-
exports.
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
exports.TRON_CHAIN_PREFIX = 'tron:';
|
|
31
|
-
// Default networks
|
|
32
|
-
exports.SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';
|
|
33
|
-
exports.SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';
|
|
34
|
-
exports.SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';
|
|
35
|
-
exports.BITCOIN_MAINNET = 'bip122:000000000019d6689c085ae165831e93';
|
|
36
|
-
exports.BITCOIN_TESTNET = 'bip122:000000000933ea01ad0ee984209779ba';
|
|
37
|
-
exports.TRON_MAINNET = 'tron:728126428';
|
|
38
|
-
exports.TRON_SHASTA = 'tron:2494104990';
|
|
39
|
-
exports.TRON_NILE = 'tron:3448148188';
|
|
40
|
-
// Hex format alternatives for Tron
|
|
41
|
-
exports.TRON_MAINNET_HEX = 'tron:0x2b6653dc';
|
|
42
|
-
exports.TRON_SHASTA_HEX = 'tron:0x94a9059e';
|
|
43
|
-
exports.TRON_NILE_HEX = 'tron:0xcd8690dc';
|
|
44
|
-
// Default poll intervals
|
|
45
|
-
exports.DEFAULT_SOLANA_POLL_INTERVAL = 30000; // 30 seconds
|
|
46
|
-
exports.DEFAULT_BITCOIN_POLL_INTERVAL = 60000; // 1 minute
|
|
47
|
-
exports.DEFAULT_TRON_POLL_INTERVAL = 30000; // 30 seconds
|
|
48
|
-
exports.DEFAULT_SNAP_POLL_INTERVAL = 30000; // Default for unknown snaps
|
|
49
|
-
// All default networks
|
|
50
|
-
exports.ALL_DEFAULT_NETWORKS = [
|
|
51
|
-
exports.SOLANA_MAINNET,
|
|
52
|
-
exports.SOLANA_DEVNET,
|
|
53
|
-
exports.SOLANA_TESTNET,
|
|
54
|
-
exports.BITCOIN_MAINNET,
|
|
55
|
-
exports.BITCOIN_TESTNET,
|
|
56
|
-
exports.TRON_MAINNET,
|
|
57
|
-
exports.TRON_SHASTA,
|
|
58
|
-
exports.TRON_NILE,
|
|
59
|
-
exports.TRON_MAINNET_HEX,
|
|
60
|
-
exports.TRON_SHASTA_HEX,
|
|
61
|
-
exports.TRON_NILE_HEX,
|
|
62
|
-
];
|
|
63
|
-
exports.SNAP_REGISTRY = {
|
|
64
|
-
solana: {
|
|
65
|
-
snapId: exports.SOLANA_SNAP_ID,
|
|
66
|
-
chainPrefix: exports.SOLANA_CHAIN_PREFIX,
|
|
67
|
-
pollInterval: exports.DEFAULT_SOLANA_POLL_INTERVAL,
|
|
68
|
-
},
|
|
69
|
-
bitcoin: {
|
|
70
|
-
snapId: exports.BITCOIN_SNAP_ID,
|
|
71
|
-
chainPrefix: exports.BITCOIN_CHAIN_PREFIX,
|
|
72
|
-
pollInterval: exports.DEFAULT_BITCOIN_POLL_INTERVAL,
|
|
73
|
-
},
|
|
74
|
-
tron: {
|
|
75
|
-
snapId: exports.TRON_SNAP_ID,
|
|
76
|
-
chainPrefix: exports.TRON_CHAIN_PREFIX,
|
|
77
|
-
pollInterval: exports.DEFAULT_TRON_POLL_INTERVAL,
|
|
78
|
-
},
|
|
79
|
-
};
|
|
25
|
+
/** The permission name for snap keyring endowment */
|
|
26
|
+
exports.KEYRING_PERMISSION = 'endowment:keyring';
|
|
27
|
+
/** The permission name for snap assets endowment (contains chainIds) */
|
|
28
|
+
exports.ASSETS_PERMISSION = 'endowment:assets';
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// PERMISSION UTILITIES
|
|
31
|
+
// ============================================================================
|
|
80
32
|
/**
|
|
81
|
-
*
|
|
33
|
+
* Getter function to get the chainIds caveat from a permission.
|
|
82
34
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
|
|
86
|
-
function getSnapTypeForChain(chainId) {
|
|
87
|
-
if (chainId.startsWith(exports.SOLANA_CHAIN_PREFIX)) {
|
|
88
|
-
return 'solana';
|
|
89
|
-
}
|
|
90
|
-
if (chainId.startsWith(exports.BITCOIN_CHAIN_PREFIX)) {
|
|
91
|
-
return 'bitcoin';
|
|
92
|
-
}
|
|
93
|
-
if (chainId.startsWith(exports.TRON_CHAIN_PREFIX)) {
|
|
94
|
-
return 'tron';
|
|
95
|
-
}
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
exports.getSnapTypeForChain = getSnapTypeForChain;
|
|
99
|
-
/**
|
|
100
|
-
* Check if a chain ID is supported by a snap.
|
|
35
|
+
* This does basic validation of the caveat, but does not validate the type or
|
|
36
|
+
* value of the namespaces object itself, as this is handled by the
|
|
37
|
+
* `PermissionsController` when the permission is requested.
|
|
101
38
|
*
|
|
102
|
-
* @param
|
|
103
|
-
* @returns
|
|
39
|
+
* @param permission - The permission to get the `chainIds` caveat from.
|
|
40
|
+
* @returns An array of `chainIds` that the snap supports, or null if none.
|
|
104
41
|
*/
|
|
105
|
-
function
|
|
106
|
-
|
|
42
|
+
function getChainIdsCaveat(permission) {
|
|
43
|
+
if (!permission?.caveats) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const caveat = permission.caveats.find((permCaveat) => permCaveat.type === snaps_utils_1.SnapCaveatType.ChainIds);
|
|
47
|
+
return caveat ? caveat.value : null;
|
|
107
48
|
}
|
|
108
|
-
exports.
|
|
49
|
+
exports.getChainIdsCaveat = getChainIdsCaveat;
|
|
109
50
|
/**
|
|
110
51
|
* Extract chain ID from a CAIP-19 asset ID.
|
|
111
52
|
* e.g., "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501" -> "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
|
|
@@ -118,26 +59,9 @@ function extractChainFromAssetId(assetId) {
|
|
|
118
59
|
return parts[0];
|
|
119
60
|
}
|
|
120
61
|
exports.extractChainFromAssetId = extractChainFromAssetId;
|
|
121
|
-
// Helper functions for specific chain types
|
|
122
|
-
function isSolanaChain(chainId) {
|
|
123
|
-
return chainId.startsWith(exports.SOLANA_CHAIN_PREFIX);
|
|
124
|
-
}
|
|
125
|
-
exports.isSolanaChain = isSolanaChain;
|
|
126
|
-
function isBitcoinChain(chainId) {
|
|
127
|
-
return chainId.startsWith(exports.BITCOIN_CHAIN_PREFIX);
|
|
128
|
-
}
|
|
129
|
-
exports.isBitcoinChain = isBitcoinChain;
|
|
130
|
-
function isTronChain(chainId) {
|
|
131
|
-
return chainId.startsWith(exports.TRON_CHAIN_PREFIX);
|
|
132
|
-
}
|
|
133
|
-
exports.isTronChain = isTronChain;
|
|
134
62
|
const defaultSnapState = {
|
|
135
|
-
activeChains:
|
|
136
|
-
|
|
137
|
-
solana: { version: null, available: false },
|
|
138
|
-
bitcoin: { version: null, available: false },
|
|
139
|
-
tron: { version: null, available: false },
|
|
140
|
-
},
|
|
63
|
+
activeChains: [],
|
|
64
|
+
chainToSnap: {},
|
|
141
65
|
};
|
|
142
66
|
// ============================================================================
|
|
143
67
|
// SNAP DATA SOURCE
|
|
@@ -146,16 +70,10 @@ const defaultSnapState = {
|
|
|
146
70
|
* Unified Snap data source that routes requests to the appropriate wallet snap
|
|
147
71
|
* based on the chain ID prefix.
|
|
148
72
|
*
|
|
149
|
-
* Supports:
|
|
150
|
-
* - Solana chains (solana:*) → @metamask/solana-wallet-snap
|
|
151
|
-
* - Bitcoin chains (bip122:*) → @metamask/bitcoin-wallet-snap
|
|
152
|
-
* - Tron chains (tron:*) → @metamask/tron-wallet-snap
|
|
153
|
-
*
|
|
154
73
|
* @example
|
|
155
74
|
* ```typescript
|
|
156
75
|
* const snapDataSource = new SnapDataSource({
|
|
157
76
|
* messenger,
|
|
158
|
-
* snapProvider: metamaskProvider,
|
|
159
77
|
* });
|
|
160
78
|
*
|
|
161
79
|
* // Fetch will automatically route to the correct snap
|
|
@@ -167,122 +85,81 @@ const defaultSnapState = {
|
|
|
167
85
|
*/
|
|
168
86
|
class SnapDataSource extends AbstractDataSource_1.AbstractDataSource {
|
|
169
87
|
constructor(options) {
|
|
170
|
-
const configuredNetworks = options.configuredNetworks ?? exports.ALL_DEFAULT_NETWORKS;
|
|
171
88
|
super(exports.SNAP_DATA_SOURCE_NAME, {
|
|
172
89
|
...defaultSnapState,
|
|
173
90
|
...options.state,
|
|
174
|
-
activeChains: configuredNetworks,
|
|
175
91
|
});
|
|
176
92
|
_SnapDataSource_instances.add(this);
|
|
177
93
|
_SnapDataSource_messenger.set(this, void 0);
|
|
178
|
-
|
|
94
|
+
/** Bound handler for snap keyring balance updates, stored for cleanup */
|
|
95
|
+
_SnapDataSource_handleSnapBalancesUpdatedBound.set(this, void 0);
|
|
96
|
+
_SnapDataSource_handlePermissionStateChangeBound.set(this, void 0);
|
|
97
|
+
/** Cache of KeyringClient instances per snap ID to avoid re-instantiation */
|
|
98
|
+
_SnapDataSource_keyringClientCache.set(this, new Map());
|
|
179
99
|
__classPrivateFieldSet(this, _SnapDataSource_messenger, options.messenger, "f");
|
|
180
|
-
|
|
100
|
+
// Bind handlers for cleanup in destroy()
|
|
101
|
+
__classPrivateFieldSet(this, _SnapDataSource_handleSnapBalancesUpdatedBound, __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_handleSnapBalancesUpdated).bind(this), "f");
|
|
102
|
+
__classPrivateFieldSet(this, _SnapDataSource_handlePermissionStateChangeBound, __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_discoverKeyringSnaps).bind(this), "f");
|
|
181
103
|
__classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_registerActionHandlers).call(this);
|
|
182
|
-
__classPrivateFieldGet(this, _SnapDataSource_instances, "m",
|
|
183
|
-
//
|
|
184
|
-
__classPrivateFieldGet(this, _SnapDataSource_instances, "m",
|
|
185
|
-
// Silently ignore availability check failures on init
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Get info about all snaps.
|
|
190
|
-
*
|
|
191
|
-
* @returns Record of snap info keyed by snap type.
|
|
192
|
-
*/
|
|
193
|
-
getSnapsInfo() {
|
|
194
|
-
const result = {};
|
|
195
|
-
for (const [snapType, config] of Object.entries(exports.SNAP_REGISTRY)) {
|
|
196
|
-
const state = this.state.snaps[snapType];
|
|
197
|
-
result[snapType] = {
|
|
198
|
-
...config,
|
|
199
|
-
version: state.version,
|
|
200
|
-
available: state.available,
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
return result;
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Check if a specific snap is available.
|
|
207
|
-
*
|
|
208
|
-
* @param snapType - The snap type to check (solana, bitcoin, tron).
|
|
209
|
-
* @returns True if the snap is available.
|
|
210
|
-
*/
|
|
211
|
-
isSnapAvailable(snapType) {
|
|
212
|
-
return this.state.snaps[snapType]?.available ?? false;
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Force refresh snap availability check.
|
|
216
|
-
*/
|
|
217
|
-
async refreshSnapsStatus() {
|
|
218
|
-
await __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_checkAllSnapsAvailability).call(this);
|
|
104
|
+
__classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_subscribeToEvents).call(this);
|
|
105
|
+
// Discover keyring-capable snaps and populate activeChains dynamically
|
|
106
|
+
__classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_discoverKeyringSnaps).call(this);
|
|
219
107
|
}
|
|
220
108
|
// ============================================================================
|
|
221
|
-
//
|
|
222
|
-
// ============================================================================
|
|
223
|
-
addNetworks(chainIds) {
|
|
224
|
-
const snapChains = chainIds.filter(isSnapSupportedChain);
|
|
225
|
-
const newChains = snapChains.filter((chain) => !this.state.activeChains.includes(chain));
|
|
226
|
-
if (newChains.length > 0) {
|
|
227
|
-
const updated = [...this.state.activeChains, ...newChains];
|
|
228
|
-
this.updateActiveChains(updated, (updatedChains) => __classPrivateFieldGet(this, _SnapDataSource_messenger, "f").call('AssetsController:activeChainsUpdate', exports.SNAP_DATA_SOURCE_NAME, updatedChains));
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
removeNetworks(chainIds) {
|
|
232
|
-
const chainSet = new Set(chainIds);
|
|
233
|
-
const updated = this.state.activeChains.filter((chain) => !chainSet.has(chain));
|
|
234
|
-
if (updated.length !== this.state.activeChains.length) {
|
|
235
|
-
this.updateActiveChains(updated, (updatedChains) => __classPrivateFieldGet(this, _SnapDataSource_messenger, "f").call('AssetsController:activeChainsUpdate', exports.SNAP_DATA_SOURCE_NAME, updatedChains));
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
// ============================================================================
|
|
239
|
-
// FETCH - Routes to appropriate snap(s)
|
|
109
|
+
// FETCH
|
|
240
110
|
// ============================================================================
|
|
241
111
|
async fetch(request) {
|
|
242
|
-
|
|
243
|
-
|
|
112
|
+
var _a;
|
|
113
|
+
// Guard against undefined request
|
|
114
|
+
// Note: chainIds filtering is done by middleware/subscribe before calling fetch
|
|
115
|
+
if (!request?.accounts || !request?.chainIds?.length) {
|
|
244
116
|
return {};
|
|
245
117
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
...request,
|
|
257
|
-
chainIds: chains,
|
|
258
|
-
});
|
|
259
|
-
}));
|
|
260
|
-
// Merge all results
|
|
261
|
-
const mergedResponse = {};
|
|
262
|
-
for (const result of results) {
|
|
263
|
-
if (result.assetsBalance) {
|
|
264
|
-
mergedResponse.assetsBalance = {
|
|
265
|
-
...mergedResponse.assetsBalance,
|
|
266
|
-
...result.assetsBalance,
|
|
267
|
-
};
|
|
118
|
+
const results = {
|
|
119
|
+
assetsBalance: {},
|
|
120
|
+
assetsMetadata: {},
|
|
121
|
+
};
|
|
122
|
+
// Fetch balances for each account using its snap ID from metadata
|
|
123
|
+
for (const account of request.accounts) {
|
|
124
|
+
// Skip accounts without snap metadata (non-snap accounts)
|
|
125
|
+
const snapId = account.metadata.snap?.id;
|
|
126
|
+
if (!snapId) {
|
|
127
|
+
continue;
|
|
268
128
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
};
|
|
129
|
+
// Skip accounts whose snap doesn't support any of the requested chains
|
|
130
|
+
const snapSupportsRequestedChains = request.chainIds.some((chainId) => this.state.chainToSnap[chainId] === snapId);
|
|
131
|
+
if (!snapSupportsRequestedChains) {
|
|
132
|
+
continue;
|
|
274
133
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
134
|
+
const accountId = account.id;
|
|
135
|
+
try {
|
|
136
|
+
const client = __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_getKeyringClient).call(this, snapId);
|
|
137
|
+
// Step 1: Get the list of assets for this account
|
|
138
|
+
const accountAssets = await client.listAccountAssets(accountId);
|
|
139
|
+
// If no assets, skip to next account
|
|
140
|
+
if (!accountAssets || accountAssets.length === 0) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// Step 2: Get balances for those specific assets
|
|
144
|
+
const balances = await client.getAccountBalances(accountId, accountAssets);
|
|
145
|
+
// Transform keyring response to DataResponse format
|
|
146
|
+
if (balances && typeof balances === 'object' && results.assetsBalance) {
|
|
147
|
+
for (const [assetId, balance] of Object.entries(balances)) {
|
|
148
|
+
(_a = results.assetsBalance)[accountId] ?? (_a[accountId] = {});
|
|
149
|
+
const accountBalances = results.assetsBalance[accountId];
|
|
150
|
+
if (accountBalances) {
|
|
151
|
+
accountBalances[assetId] = {
|
|
152
|
+
amount: balance.amount,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
280
157
|
}
|
|
281
|
-
|
|
282
|
-
|
|
158
|
+
catch {
|
|
159
|
+
// Expected when account doesn't belong to this snap
|
|
283
160
|
}
|
|
284
161
|
}
|
|
285
|
-
return
|
|
162
|
+
return results;
|
|
286
163
|
}
|
|
287
164
|
// ============================================================================
|
|
288
165
|
// MIDDLEWARE
|
|
@@ -370,19 +247,19 @@ class SnapDataSource extends AbstractDataSource_1.AbstractDataSource {
|
|
|
370
247
|
if (!request?.chainIds) {
|
|
371
248
|
return;
|
|
372
249
|
}
|
|
373
|
-
// Filter to
|
|
374
|
-
const
|
|
375
|
-
if (
|
|
250
|
+
// Filter to chains we have a snap for
|
|
251
|
+
const supportedChains = request.chainIds.filter((chainId) => __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_isChainSupportedBySnap).call(this, chainId));
|
|
252
|
+
if (supportedChains.length === 0) {
|
|
376
253
|
return;
|
|
377
254
|
}
|
|
378
255
|
if (isUpdate) {
|
|
379
256
|
const existing = this.activeSubscriptions.get(subscriptionId);
|
|
380
257
|
if (existing) {
|
|
381
|
-
existing.chains =
|
|
258
|
+
existing.chains = supportedChains;
|
|
382
259
|
// Do a fetch to get latest data on subscription update
|
|
383
260
|
this.fetch({
|
|
384
261
|
...request,
|
|
385
|
-
chainIds:
|
|
262
|
+
chainIds: supportedChains,
|
|
386
263
|
})
|
|
387
264
|
.then(async (fetchResponse) => {
|
|
388
265
|
if (Object.keys(fetchResponse.assetsBalance ?? {}).length > 0) {
|
|
@@ -404,13 +281,13 @@ class SnapDataSource extends AbstractDataSource_1.AbstractDataSource {
|
|
|
404
281
|
cleanup: () => {
|
|
405
282
|
// No timer to clear - we use event-based updates
|
|
406
283
|
},
|
|
407
|
-
chains:
|
|
284
|
+
chains: supportedChains,
|
|
408
285
|
});
|
|
409
286
|
// Initial fetch to get current balances
|
|
410
287
|
try {
|
|
411
288
|
const fetchResponse = await this.fetch({
|
|
412
289
|
...request,
|
|
413
|
-
chainIds:
|
|
290
|
+
chainIds: supportedChains,
|
|
414
291
|
});
|
|
415
292
|
if (Object.keys(fetchResponse.assetsBalance ?? {}).length > 0) {
|
|
416
293
|
await __classPrivateFieldGet(this, _SnapDataSource_messenger, "f").call('AssetsController:assetsUpdate', fetchResponse, exports.SNAP_DATA_SOURCE_NAME);
|
|
@@ -424,53 +301,69 @@ class SnapDataSource extends AbstractDataSource_1.AbstractDataSource {
|
|
|
424
301
|
// CLEANUP
|
|
425
302
|
// ============================================================================
|
|
426
303
|
destroy() {
|
|
304
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
305
|
+
const messenger = __classPrivateFieldGet(this, _SnapDataSource_messenger, "f");
|
|
306
|
+
// Unsubscribe from snap keyring events
|
|
307
|
+
try {
|
|
308
|
+
messenger.unsubscribe('AccountsController:accountBalancesUpdated', __classPrivateFieldGet(this, _SnapDataSource_handleSnapBalancesUpdatedBound, "f"));
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
log('Failed to unsubscribe from snap keyring events', { error });
|
|
312
|
+
}
|
|
313
|
+
// Unsubscribe from permission changes
|
|
314
|
+
try {
|
|
315
|
+
messenger.unsubscribe('PermissionController:stateChange', __classPrivateFieldGet(this, _SnapDataSource_handlePermissionStateChangeBound, "f"));
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
log('Failed to unsubscribe from permission changes', { error });
|
|
319
|
+
}
|
|
320
|
+
// Clean up active subscriptions
|
|
427
321
|
for (const [subscriptionId] of this.activeSubscriptions) {
|
|
428
322
|
this.unsubscribe(subscriptionId).catch(() => {
|
|
429
323
|
// Ignore cleanup errors
|
|
430
324
|
});
|
|
431
325
|
}
|
|
326
|
+
// Clear keyring client cache
|
|
327
|
+
__classPrivateFieldGet(this, _SnapDataSource_keyringClientCache, "f").clear();
|
|
432
328
|
}
|
|
433
329
|
}
|
|
434
330
|
exports.SnapDataSource = SnapDataSource;
|
|
435
|
-
_SnapDataSource_messenger = new WeakMap(),
|
|
436
|
-
//
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
catch (error) {
|
|
444
|
-
log('Failed to subscribe to snap keyring events', { error });
|
|
445
|
-
}
|
|
331
|
+
_SnapDataSource_messenger = new WeakMap(), _SnapDataSource_handleSnapBalancesUpdatedBound = new WeakMap(), _SnapDataSource_handlePermissionStateChangeBound = new WeakMap(), _SnapDataSource_keyringClientCache = new WeakMap(), _SnapDataSource_instances = new WeakSet(), _SnapDataSource_subscribeToEvents = function _SnapDataSource_subscribeToEvents() {
|
|
332
|
+
// Subscribe to snap keyring events for real-time balance updates.
|
|
333
|
+
// The snaps emit AccountBalancesUpdated events when balances change,
|
|
334
|
+
// which are re-published by AccountsController.
|
|
335
|
+
__classPrivateFieldGet(this, _SnapDataSource_messenger, "f").subscribe('AccountsController:accountBalancesUpdated', __classPrivateFieldGet(this, _SnapDataSource_handleSnapBalancesUpdatedBound, "f"));
|
|
336
|
+
// Subscribe to permission changes to detect new keyring snaps at runtime.
|
|
337
|
+
// Re-runs snap discovery when permissions change.
|
|
338
|
+
__classPrivateFieldGet(this, _SnapDataSource_messenger, "f").subscribe('PermissionController:stateChange', __classPrivateFieldGet(this, _SnapDataSource_handlePermissionStateChangeBound, "f"));
|
|
446
339
|
}, _SnapDataSource_handleSnapBalancesUpdated = function _SnapDataSource_handleSnapBalancesUpdated(payload) {
|
|
447
340
|
// Transform the snap keyring payload to DataResponse format
|
|
448
|
-
|
|
449
|
-
assetsBalance: {},
|
|
450
|
-
};
|
|
341
|
+
let assetsBalance;
|
|
451
342
|
for (const [accountId, assets] of Object.entries(payload.balances)) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
// Remove account if no snap assets
|
|
463
|
-
if (Object.keys(response.assetsBalance[accountId]).length === 0) {
|
|
464
|
-
delete response.assetsBalance[accountId];
|
|
343
|
+
let accountAssets;
|
|
344
|
+
for (const [assetId, balance] of Object.entries(assets)) {
|
|
345
|
+
const chainId = extractChainFromAssetId(assetId);
|
|
346
|
+
if (__classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_isChainSupportedBySnap).call(this, chainId)) {
|
|
347
|
+
accountAssets ?? (accountAssets = {});
|
|
348
|
+
accountAssets[assetId] = {
|
|
349
|
+
amount: balance.amount,
|
|
350
|
+
};
|
|
465
351
|
}
|
|
466
352
|
}
|
|
353
|
+
if (accountAssets) {
|
|
354
|
+
assetsBalance ?? (assetsBalance = {});
|
|
355
|
+
assetsBalance[accountId] = accountAssets;
|
|
356
|
+
}
|
|
467
357
|
}
|
|
468
358
|
// Only report if we have snap-related updates
|
|
469
|
-
if (
|
|
359
|
+
if (assetsBalance) {
|
|
360
|
+
const response = { assetsBalance };
|
|
470
361
|
__classPrivateFieldGet(this, _SnapDataSource_messenger, "f")
|
|
471
362
|
.call('AssetsController:assetsUpdate', response, exports.SNAP_DATA_SOURCE_NAME)
|
|
472
363
|
.catch(console.error);
|
|
473
364
|
}
|
|
365
|
+
}, _SnapDataSource_isChainSupportedBySnap = function _SnapDataSource_isChainSupportedBySnap(chainId) {
|
|
366
|
+
return this.state.activeChains.includes(chainId);
|
|
474
367
|
}, _SnapDataSource_registerActionHandlers = function _SnapDataSource_registerActionHandlers() {
|
|
475
368
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
476
369
|
const messenger = __classPrivateFieldGet(this, _SnapDataSource_messenger, "f");
|
|
@@ -479,250 +372,86 @@ _SnapDataSource_messenger = new WeakMap(), _SnapDataSource_snapProvider = new We
|
|
|
479
372
|
messenger.registerActionHandler('SnapDataSource:fetch', async (request) => this.fetch(request));
|
|
480
373
|
messenger.registerActionHandler('SnapDataSource:subscribe', async (request) => this.subscribe(request));
|
|
481
374
|
messenger.registerActionHandler('SnapDataSource:unsubscribe', async (subscriptionId) => this.unsubscribe(subscriptionId));
|
|
482
|
-
},
|
|
483
|
-
// ============================================================================
|
|
484
|
-
// SNAP AVAILABILITY
|
|
485
|
-
// ============================================================================
|
|
486
|
-
/**
|
|
487
|
-
* Get all installed snaps from the snap provider.
|
|
488
|
-
*
|
|
489
|
-
* @returns A map of snap IDs to their versions.
|
|
490
|
-
*/
|
|
491
|
-
async function _SnapDataSource_getInstalledSnaps() {
|
|
375
|
+
}, _SnapDataSource_getRunnableSnaps = function _SnapDataSource_getRunnableSnaps() {
|
|
492
376
|
try {
|
|
493
|
-
|
|
494
|
-
method: 'wallet_getSnaps',
|
|
495
|
-
params: {},
|
|
496
|
-
});
|
|
497
|
-
return snaps;
|
|
377
|
+
return __classPrivateFieldGet(this, _SnapDataSource_messenger, "f").call('SnapController:getRunnableSnaps');
|
|
498
378
|
}
|
|
499
379
|
catch (error) {
|
|
500
|
-
log('Failed to get
|
|
501
|
-
return
|
|
380
|
+
log('Failed to get runnable snaps', error);
|
|
381
|
+
return [];
|
|
502
382
|
}
|
|
503
|
-
},
|
|
504
|
-
/**
|
|
505
|
-
* Check availability for a single snap type on-demand.
|
|
506
|
-
* This is called before each fetch to ensure we have the latest availability status.
|
|
507
|
-
*
|
|
508
|
-
* @param snapType - The snap type to check (solana, bitcoin, tron)
|
|
509
|
-
* @returns True if the snap is available, false otherwise
|
|
510
|
-
*/
|
|
511
|
-
async function _SnapDataSource_checkSnapAvailabilityOnDemand(snapType) {
|
|
512
|
-
const config = exports.SNAP_REGISTRY[snapType];
|
|
513
|
-
const currentState = this.state.snaps[snapType];
|
|
514
|
-
// If already marked as available, return true (snap was found previously)
|
|
515
|
-
if (currentState.available) {
|
|
516
|
-
return true;
|
|
517
|
-
}
|
|
518
|
-
// Check if snap is now available (handles timing issues where snap wasn't ready at init)
|
|
383
|
+
}, _SnapDataSource_getSnapPermissions = function _SnapDataSource_getSnapPermissions(snapId) {
|
|
519
384
|
try {
|
|
520
|
-
|
|
521
|
-
const snap = snaps[config.snapId];
|
|
522
|
-
if (snap) {
|
|
523
|
-
// Snap is now available - update state
|
|
524
|
-
this.state.snaps[snapType] = {
|
|
525
|
-
version: snap.version,
|
|
526
|
-
available: true,
|
|
527
|
-
};
|
|
528
|
-
return true;
|
|
529
|
-
}
|
|
530
|
-
return false;
|
|
385
|
+
return __classPrivateFieldGet(this, _SnapDataSource_messenger, "f").call('PermissionController:getPermissions', snapId);
|
|
531
386
|
}
|
|
532
|
-
catch {
|
|
533
|
-
|
|
387
|
+
catch (error) {
|
|
388
|
+
log('Failed to get permissions for snap', { snapId, error });
|
|
389
|
+
return undefined;
|
|
534
390
|
}
|
|
535
|
-
},
|
|
391
|
+
}, _SnapDataSource_discoverKeyringSnaps = function _SnapDataSource_discoverKeyringSnaps() {
|
|
536
392
|
try {
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
393
|
+
const runnableSnaps = __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_getRunnableSnaps).call(this);
|
|
394
|
+
const chainToSnap = {};
|
|
395
|
+
const supportedChains = [];
|
|
396
|
+
for (const snap of runnableSnaps) {
|
|
397
|
+
const permissions = __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_getSnapPermissions).call(this, snap.id);
|
|
398
|
+
// Must have endowment:keyring permission to be a keyring snap
|
|
399
|
+
if (!permissions?.[exports.KEYRING_PERMISSION]) {
|
|
400
|
+
continue;
|
|
545
401
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
402
|
+
// Get chainIds caveat from the assets permission (not keyring permission)
|
|
403
|
+
// The chainIds are stored in endowment:assets
|
|
404
|
+
const assetsPermission = permissions[exports.ASSETS_PERMISSION];
|
|
405
|
+
const chainIds = getChainIdsCaveat(assetsPermission);
|
|
406
|
+
// Map each chain to this snap (first snap wins if multiple support same chain)
|
|
407
|
+
if (chainIds) {
|
|
408
|
+
for (const chainId of chainIds) {
|
|
409
|
+
if (!(chainId in chainToSnap)) {
|
|
410
|
+
chainToSnap[chainId] = snap.id;
|
|
411
|
+
supportedChains.push(chainId);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
551
414
|
}
|
|
552
415
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
//
|
|
556
|
-
|
|
557
|
-
this.
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}, _SnapDataSource_accountSupportsChain = function _SnapDataSource_accountSupportsChain(account, chainId) {
|
|
564
|
-
const scopes = account.scopes ?? [];
|
|
565
|
-
// If no scopes defined, assume it supports the chain (backward compatibility)
|
|
566
|
-
if (scopes.length === 0) {
|
|
567
|
-
return true;
|
|
568
|
-
}
|
|
569
|
-
// Extract namespace and reference from chainId
|
|
570
|
-
const [chainNamespace, chainReference] = chainId.split(':');
|
|
571
|
-
for (const scope of scopes) {
|
|
572
|
-
const [scopeNamespace, scopeReference] = scope.split(':');
|
|
573
|
-
// Check if namespaces match
|
|
574
|
-
if (scopeNamespace !== chainNamespace) {
|
|
575
|
-
continue;
|
|
576
|
-
}
|
|
577
|
-
// Wildcard scope (e.g., "solana:0" means all chains in that namespace)
|
|
578
|
-
if (scopeReference === '0') {
|
|
579
|
-
return true;
|
|
580
|
-
}
|
|
581
|
-
// Exact match check
|
|
582
|
-
if (scopeReference === chainReference) {
|
|
583
|
-
return true;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
return false;
|
|
587
|
-
}, _SnapDataSource_groupChainsBySnap = function _SnapDataSource_groupChainsBySnap(chainIds) {
|
|
588
|
-
const groups = {};
|
|
589
|
-
for (const chainId of chainIds) {
|
|
590
|
-
const snapType = getSnapTypeForChain(chainId);
|
|
591
|
-
if (snapType) {
|
|
592
|
-
groups[snapType] ?? (groups[snapType] = []);
|
|
593
|
-
const snapChains = groups[snapType];
|
|
594
|
-
if (snapChains) {
|
|
595
|
-
snapChains.push(chainId);
|
|
596
|
-
}
|
|
416
|
+
// Update chainToSnap mapping
|
|
417
|
+
this.state.chainToSnap = chainToSnap;
|
|
418
|
+
// Notify if chains changed
|
|
419
|
+
try {
|
|
420
|
+
this.updateActiveChains(supportedChains, (updatedChains) => {
|
|
421
|
+
__classPrivateFieldGet(this, _SnapDataSource_messenger, "f").call('AssetsController:activeChainsUpdate', exports.SNAP_DATA_SOURCE_NAME, updatedChains);
|
|
422
|
+
});
|
|
597
423
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}, _SnapDataSource_fetchFromSnap = async function _SnapDataSource_fetchFromSnap(snapType, request) {
|
|
601
|
-
var _a;
|
|
602
|
-
const config = exports.SNAP_REGISTRY[snapType];
|
|
603
|
-
// Check snap availability on-demand - handles timing issues where snap
|
|
604
|
-
// wasn't ready during initialization but is now available
|
|
605
|
-
const isAvailable = await __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_checkSnapAvailabilityOnDemand).call(this, snapType);
|
|
606
|
-
if (!isAvailable) {
|
|
607
|
-
log(`${snapType} snap not available, skipping fetch`);
|
|
608
|
-
// Return errors for these chains so they can fallback to other data sources
|
|
609
|
-
const errors = {};
|
|
610
|
-
for (const chainId of request.chainIds) {
|
|
611
|
-
errors[chainId] = `${snapType} snap not available`;
|
|
424
|
+
catch {
|
|
425
|
+
// AssetsController not ready yet - expected during initialization
|
|
612
426
|
}
|
|
613
|
-
return { errors };
|
|
614
427
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
};
|
|
619
|
-
// Fetch balances for each account using Keyring API
|
|
620
|
-
// Important: Must first get account assets, then request balances for those specific assets
|
|
621
|
-
for (const account of request.accounts) {
|
|
622
|
-
// Filter to only process accounts that support the chains being fetched
|
|
623
|
-
const accountSupportedChains = request.chainIds.filter((chainId) => __classPrivateFieldGet(this, _SnapDataSource_instances, "m", _SnapDataSource_accountSupportsChain).call(this, account, chainId));
|
|
624
|
-
// Skip accounts that don't support any of the requested chains
|
|
625
|
-
if (accountSupportedChains.length === 0) {
|
|
626
|
-
continue;
|
|
627
|
-
}
|
|
628
|
-
const accountId = account.id;
|
|
428
|
+
catch (error) {
|
|
429
|
+
log('Keyring snap discovery failed', { error });
|
|
430
|
+
this.state.chainToSnap = {};
|
|
629
431
|
try {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
snapId: config.snapId,
|
|
633
|
-
accountId,
|
|
634
|
-
});
|
|
635
|
-
const accountAssets = await __classPrivateFieldGet(this, _SnapDataSource_snapProvider, "f").request({
|
|
636
|
-
method: 'wallet_invokeSnap',
|
|
637
|
-
params: {
|
|
638
|
-
snapId: config.snapId,
|
|
639
|
-
request: {
|
|
640
|
-
method: 'keyring_listAccountAssets',
|
|
641
|
-
params: {
|
|
642
|
-
id: accountId, // Account UUID
|
|
643
|
-
},
|
|
644
|
-
},
|
|
645
|
-
},
|
|
646
|
-
});
|
|
647
|
-
log(`${snapType} snap keyring_listAccountAssets response`, {
|
|
648
|
-
accountId,
|
|
649
|
-
assetCount: accountAssets?.length ?? 0,
|
|
650
|
-
assets: accountAssets,
|
|
651
|
-
});
|
|
652
|
-
// If no assets, skip to next account
|
|
653
|
-
if (!accountAssets || accountAssets.length === 0) {
|
|
654
|
-
log(`${snapType} snap: account has no assets, skipping balance fetch`, {
|
|
655
|
-
accountId,
|
|
656
|
-
});
|
|
657
|
-
continue;
|
|
658
|
-
}
|
|
659
|
-
// Step 2: Get balances for those specific assets
|
|
660
|
-
log(`${snapType} snap calling keyring_getAccountBalances`, {
|
|
661
|
-
snapId: config.snapId,
|
|
662
|
-
accountId,
|
|
663
|
-
requestedAssets: accountAssets.length,
|
|
664
|
-
});
|
|
665
|
-
const balances = await __classPrivateFieldGet(this, _SnapDataSource_snapProvider, "f").request({
|
|
666
|
-
method: 'wallet_invokeSnap',
|
|
667
|
-
params: {
|
|
668
|
-
snapId: config.snapId,
|
|
669
|
-
request: {
|
|
670
|
-
method: 'keyring_getAccountBalances',
|
|
671
|
-
params: {
|
|
672
|
-
id: accountId, // Account UUID (the keyring API uses 'id' not 'accountId')
|
|
673
|
-
assets: accountAssets, // Must pass specific asset types from listAccountAssets
|
|
674
|
-
},
|
|
675
|
-
},
|
|
676
|
-
},
|
|
677
|
-
});
|
|
678
|
-
log(`${snapType} snap keyring_getAccountBalances response`, {
|
|
679
|
-
accountId,
|
|
680
|
-
balances,
|
|
681
|
-
balancesType: typeof balances,
|
|
682
|
-
isNull: balances === null,
|
|
683
|
-
isUndefined: balances === undefined,
|
|
684
|
-
assetCount: balances ? Object.keys(balances).length : 0,
|
|
432
|
+
this.updateActiveChains([], (updatedChains) => {
|
|
433
|
+
__classPrivateFieldGet(this, _SnapDataSource_messenger, "f").call('AssetsController:activeChainsUpdate', exports.SNAP_DATA_SOURCE_NAME, updatedChains);
|
|
685
434
|
});
|
|
686
|
-
// Transform keyring response to DataResponse format
|
|
687
|
-
// Note: snap may return null/undefined if account doesn't belong to this snap
|
|
688
|
-
if (balances && typeof balances === 'object' && results.assetsBalance) {
|
|
689
|
-
const balanceEntries = Object.entries(balances);
|
|
690
|
-
log(`${snapType} snap processing ${balanceEntries.length} balances for account ${accountId}`);
|
|
691
|
-
for (const [assetId, balance] of balanceEntries) {
|
|
692
|
-
// Initialize account balances if not exists
|
|
693
|
-
(_a = results.assetsBalance)[accountId] ?? (_a[accountId] = {});
|
|
694
|
-
// Store raw balance for this asset
|
|
695
|
-
// Use rawAmount if available (preferred - smallest unit), fall back to amount
|
|
696
|
-
// Note: Snaps should return rawAmount in smallest unit (satoshis, lamports, etc.)
|
|
697
|
-
const accountBalances = results.assetsBalance[accountId];
|
|
698
|
-
if (accountBalances) {
|
|
699
|
-
accountBalances[assetId] = {
|
|
700
|
-
amount: balance.rawAmount ?? balance.amount,
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
else if (!balances) {
|
|
706
|
-
log(`${snapType} snap returned empty/null for account (account may not belong to this snap)`, {
|
|
707
|
-
accountId,
|
|
708
|
-
balances,
|
|
709
|
-
});
|
|
710
|
-
}
|
|
711
435
|
}
|
|
712
|
-
catch
|
|
713
|
-
//
|
|
714
|
-
log(`${snapType} snap fetch FAILED for account`, {
|
|
715
|
-
accountId,
|
|
716
|
-
error: error instanceof Error ? error.message : String(error),
|
|
717
|
-
errorStack: error instanceof Error ? error.stack : undefined,
|
|
718
|
-
});
|
|
436
|
+
catch {
|
|
437
|
+
// AssetsController not ready yet - expected during initialization
|
|
719
438
|
}
|
|
720
439
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
440
|
+
}, _SnapDataSource_getKeyringClient = function _SnapDataSource_getKeyringClient(snapId) {
|
|
441
|
+
const cachedClient = __classPrivateFieldGet(this, _SnapDataSource_keyringClientCache, "f").get(snapId);
|
|
442
|
+
if (cachedClient) {
|
|
443
|
+
return cachedClient;
|
|
444
|
+
}
|
|
445
|
+
const client = new keyring_snap_client_1.KeyringClient({
|
|
446
|
+
send: async (request) => (await __classPrivateFieldGet(this, _SnapDataSource_messenger, "f").call('SnapController:handleRequest', {
|
|
447
|
+
snapId: snapId,
|
|
448
|
+
origin: 'metamask',
|
|
449
|
+
handler: snaps_utils_1.HandlerType.OnKeyringRequest,
|
|
450
|
+
request,
|
|
451
|
+
})),
|
|
724
452
|
});
|
|
725
|
-
|
|
453
|
+
__classPrivateFieldGet(this, _SnapDataSource_keyringClientCache, "f").set(snapId, client);
|
|
454
|
+
return client;
|
|
726
455
|
};
|
|
727
456
|
// ============================================================================
|
|
728
457
|
// FACTORY
|