@metamask-previews/eth-snap-keyring 19.0.0-fd40efd → 20.0.0-018fb62
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 +28 -1
- package/dist/SnapKeyring.cjs +126 -70
- package/dist/SnapKeyring.cjs.map +1 -1
- package/dist/SnapKeyring.d.cts +7 -0
- package/dist/SnapKeyring.d.cts.map +1 -1
- package/dist/SnapKeyring.d.mts +7 -0
- package/dist/SnapKeyring.d.mts.map +1 -1
- package/dist/SnapKeyring.mjs +126 -70
- package/dist/SnapKeyring.mjs.map +1 -1
- package/dist/SnapKeyringMessenger.cjs.map +1 -1
- package/dist/SnapKeyringMessenger.d.cts +2 -2
- package/dist/SnapKeyringMessenger.d.cts.map +1 -1
- package/dist/SnapKeyringMessenger.d.mts +2 -2
- package/dist/SnapKeyringMessenger.d.mts.map +1 -1
- package/dist/SnapKeyringMessenger.mjs.map +1 -1
- package/dist/SnapKeyringV2.cjs +161 -0
- package/dist/SnapKeyringV2.cjs.map +1 -0
- package/dist/SnapKeyringV2.d.cts +117 -0
- package/dist/SnapKeyringV2.d.cts.map +1 -0
- package/dist/SnapKeyringV2.d.mts +117 -0
- package/dist/SnapKeyringV2.d.mts.map +1 -0
- package/dist/SnapKeyringV2.mjs +157 -0
- package/dist/SnapKeyringV2.mjs.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -10
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Add `SnapKeyringV2` class, a per-snap keyring wrapper with O(1) account lookups by ID and address ([#501](https://github.com/MetaMask/accounts/pull/501))
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Refactor `SnapKeyring` to store accounts in per-snap `SnapKeyringV2` wrappers instead of a single flat map ([#501](https://github.com/MetaMask/accounts/pull/501))
|
|
17
|
+
- Bump `@metamask/keyring-sdk` from none to `^1.1.0`
|
|
18
|
+
- Bump `@metamask/messenger` from `^0.3.0` to `^1.1.1` ([#489](https://github.com/MetaMask/accounts/pull/489), [#500](https://github.com/MetaMask/accounts/pull/500))
|
|
19
|
+
- Bump `@metamask/snaps-controllers` from `^19.0.0` to `^19.0.1` ([#500](https://github.com/MetaMask/accounts/pull/500))
|
|
20
|
+
- Bump `@metamask/snaps-utils` from `^12.1.2` to `^12.1.3` ([#500](https://github.com/MetaMask/accounts/pull/500))
|
|
21
|
+
- Bump `@metamask/utils` from `^11.1.0` to `^11.10.0` ([#489](https://github.com/MetaMask/accounts/pull/489))
|
|
22
|
+
|
|
23
|
+
## [20.0.0]
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **BREAKING:** Bump `@metamask/keyring-api` from `^21.6.0` to `^22.0.0` ([#482](https://github.com/MetaMask/accounts/pull/482))
|
|
28
|
+
- **BREAKING:** Bump `@metamask/snaps-controllers` from `^18.0.0` to `^19.0.0` ([#486](https://github.com/MetaMask/accounts/pull/486))
|
|
29
|
+
- `SnapKeyring` now requires `SnapController:getSnap` instead of `SnapController:get`.
|
|
30
|
+
- Bump `@metamask/keyring-internal-api` from `^10.0.0` to `^10.0.1` ([#482](https://github.com/MetaMask/accounts/pull/482))
|
|
31
|
+
- Bump `@metamask/keyring-internal-snap-client` from `^9.0.0` to `^9.0.1` ([#482](https://github.com/MetaMask/accounts/pull/482))
|
|
32
|
+
- Bump `@metamask/keyring-snap-sdk` from `^7.2.1` to `^8.0.0` ([#482](https://github.com/MetaMask/accounts/pull/482))
|
|
33
|
+
- Bump `@metamask/snaps-sdk` from `^10.4.0` to `^11.0.0` ([#486](https://github.com/MetaMask/accounts/pull/486))
|
|
34
|
+
- Bump `@metamask/snaps-utils` from `^12.1.0` to `^12.1.2` ([#486](https://github.com/MetaMask/accounts/pull/486))
|
|
35
|
+
|
|
10
36
|
## [19.0.0]
|
|
11
37
|
|
|
12
38
|
### Added
|
|
@@ -632,7 +658,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
632
658
|
|
|
633
659
|
- Initial release.
|
|
634
660
|
|
|
635
|
-
[Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@
|
|
661
|
+
[Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@20.0.0...HEAD
|
|
662
|
+
[20.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@19.0.0...@metamask/eth-snap-keyring@20.0.0
|
|
636
663
|
[19.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@18.0.2...@metamask/eth-snap-keyring@19.0.0
|
|
637
664
|
[18.0.2]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@18.0.1...@metamask/eth-snap-keyring@18.0.2
|
|
638
665
|
[18.0.1]: https://github.com/MetaMask/accounts/compare/@metamask/eth-snap-keyring@18.0.0...@metamask/eth-snap-keyring@18.0.1
|
package/dist/SnapKeyring.cjs
CHANGED
|
@@ -10,7 +10,7 @@ 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 _SnapKeyring_instances, _SnapKeyring_messenger, _SnapKeyring_snapClient,
|
|
13
|
+
var _SnapKeyring_instances, _SnapKeyring_messenger, _SnapKeyring_snapClient, _SnapKeyring_snapKeyrings, _SnapKeyring_accountIndex, _SnapKeyring_selectedAccounts, _SnapKeyring_requests, _SnapKeyring_options, _SnapKeyring_callbacks, _SnapKeyring_isAnyAccountTypeAllowed, _SnapKeyring_lock, _SnapKeyring_withLock, _SnapKeyring_getOrCreateKeyringV2, _SnapKeyring_isMinimumPlatformVersion, _SnapKeyring_assertAccountCanBeUsed, _SnapKeyring_getExistingAccount, _SnapKeyring_getInternalOptions, _SnapKeyring_handleAccountCreated, _SnapKeyring_handleAccountUpdated, _SnapKeyring_handleAccountDeleted, _SnapKeyring_handleGetSelectedAccounts, _SnapKeyring_handleRequestApproved, _SnapKeyring_handleRequestRejected, _SnapKeyring_rePublishAccountEvent, _SnapKeyring_handleAccountBalancesUpdated, _SnapKeyring_handleAccountAssetListUpdated, _SnapKeyring_handleAccountTransactionsUpdated, _SnapKeyring_getAccount, _SnapKeyring_submitRequest, _SnapKeyring_submitSnapRequest, _SnapKeyring_hasMethod, _SnapKeyring_createRequestPromise, _SnapKeyring_clearRequestPromise, _SnapKeyring_handleSyncResponse, _SnapKeyring_handleAsyncResponse, _SnapKeyring_sanitizeRedirectUrl, _SnapKeyring_validateRedirectUrl, _SnapKeyring_deleteAccount, _SnapKeyring_resolveAddress, _SnapKeyring_updateSelectedAccountsMap, _SnapKeyring_getSnap, _SnapKeyring_getSnapMetadata, _SnapKeyring_getSnapAllowedOrigins, _SnapKeyring_transformToInternalAccount;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.SnapKeyring = exports.SNAP_KEYRING_TYPE = void 0;
|
|
16
16
|
const tx_1 = require("@ethereumjs/tx");
|
|
@@ -28,11 +28,11 @@ const account_1 = require("./account.cjs");
|
|
|
28
28
|
const DeferredPromise_1 = require("./DeferredPromise.cjs");
|
|
29
29
|
const events_1 = require("./events.cjs");
|
|
30
30
|
const logger_1 = require("./logger.cjs");
|
|
31
|
-
const migrations_1 = require("./migrations/index.cjs");
|
|
32
31
|
const options_1 = require("./options.cjs");
|
|
33
32
|
const platform_versions_1 = require("./platform-versions.cjs");
|
|
34
33
|
const SnapIdMap_1 = require("./SnapIdMap.cjs");
|
|
35
34
|
const SnapKeyringMessenger_1 = require("./SnapKeyringMessenger.cjs");
|
|
35
|
+
const SnapKeyringV2_1 = require("./SnapKeyringV2.cjs");
|
|
36
36
|
const types_1 = require("./types.cjs");
|
|
37
37
|
const util_1 = require("./util.cjs");
|
|
38
38
|
exports.SNAP_KEYRING_TYPE = 'Snap Keyring';
|
|
@@ -77,10 +77,20 @@ class SnapKeyring {
|
|
|
77
77
|
*/
|
|
78
78
|
_SnapKeyring_snapClient.set(this, void 0);
|
|
79
79
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
80
|
+
* Per-snap keyring wrappers.
|
|
81
|
+
*
|
|
82
|
+
* Each entry owns the registry for a single Snap. Accounts are stored and
|
|
83
|
+
* looked up through these wrappers rather than through the old flat map.
|
|
84
|
+
*/
|
|
85
|
+
_SnapKeyring_snapKeyrings.set(this, void 0);
|
|
86
|
+
/**
|
|
87
|
+
* Reverse index from account ID to the owning Snap ID.
|
|
88
|
+
*
|
|
89
|
+
* Populated and kept in sync via the `onRegister` / `onUnregister`
|
|
90
|
+
* callbacks injected into each `SnapKeyringV2`. Enables O(1) routing for
|
|
91
|
+
* any "which snap owns this account?" query.
|
|
82
92
|
*/
|
|
83
|
-
|
|
93
|
+
_SnapKeyring_accountIndex.set(this, void 0);
|
|
84
94
|
/**
|
|
85
95
|
* Mapping between Snap IDs and the selected accounts.
|
|
86
96
|
*/
|
|
@@ -112,7 +122,8 @@ class SnapKeyring {
|
|
|
112
122
|
__classPrivateFieldSet(this, _SnapKeyring_messenger, messenger, "f");
|
|
113
123
|
__classPrivateFieldSet(this, _SnapKeyring_snapClient, new keyring_internal_snap_client_1.KeyringInternalSnapClient({ messenger }), "f");
|
|
114
124
|
__classPrivateFieldSet(this, _SnapKeyring_requests, new SnapIdMap_1.SnapIdMap(), "f");
|
|
115
|
-
__classPrivateFieldSet(this,
|
|
125
|
+
__classPrivateFieldSet(this, _SnapKeyring_snapKeyrings, new Map(), "f");
|
|
126
|
+
__classPrivateFieldSet(this, _SnapKeyring_accountIndex, new Map(), "f");
|
|
116
127
|
__classPrivateFieldSet(this, _SnapKeyring_options, new SnapIdMap_1.SnapIdMap(), "f");
|
|
117
128
|
__classPrivateFieldSet(this, _SnapKeyring_callbacks, callbacks, "f");
|
|
118
129
|
__classPrivateFieldSet(this, _SnapKeyring_isAnyAccountTypeAllowed, isAnyAccountTypeAllowed, "f");
|
|
@@ -164,16 +175,27 @@ class SnapKeyring {
|
|
|
164
175
|
/**
|
|
165
176
|
* Serialize the keyring state.
|
|
166
177
|
*
|
|
178
|
+
* Delegates to each per-snap wrapper and flattens back into the original
|
|
179
|
+
* external format so that `KeyringController` sees no change.
|
|
180
|
+
*
|
|
167
181
|
* @returns Serialized keyring state.
|
|
168
182
|
*/
|
|
169
183
|
async serialize() {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
184
|
+
const accounts = {};
|
|
185
|
+
for (const wrapper of __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").values()) {
|
|
186
|
+
for (const account of wrapper.accounts()) {
|
|
187
|
+
accounts[account.id] = { account, snapId: wrapper.snapId };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return { accounts };
|
|
173
191
|
}
|
|
174
192
|
/**
|
|
175
193
|
* Deserialize the keyring state into this keyring.
|
|
176
194
|
*
|
|
195
|
+
* Groups the flat persisted state by `snapId`, clears both indexes, then
|
|
196
|
+
* rebuilds each per-snap wrapper. The `onRegister` callbacks fired during
|
|
197
|
+
* `wrapper.deserialize()` automatically repopulate `#accountIndex`.
|
|
198
|
+
*
|
|
177
199
|
* @param state - Serialized keyring state.
|
|
178
200
|
*/
|
|
179
201
|
async deserialize(state) {
|
|
@@ -182,26 +204,23 @@ class SnapKeyring {
|
|
|
182
204
|
if (state === undefined) {
|
|
183
205
|
return;
|
|
184
206
|
}
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
accounts[snapId] = entry;
|
|
202
|
-
}
|
|
207
|
+
// Group flat state by snapId. Migrations and migration logging are handled
|
|
208
|
+
// inside wrapper.deserialize().
|
|
209
|
+
const bySnap = new Map();
|
|
210
|
+
for (const entry of Object.values(state.accounts)) {
|
|
211
|
+
const snapAccounts = bySnap.get(entry.snapId) ?? {};
|
|
212
|
+
snapAccounts[entry.account.id] = entry.account;
|
|
213
|
+
bySnap.set(entry.snapId, snapAccounts);
|
|
214
|
+
}
|
|
215
|
+
// Clear both indexes before rebuilding — they must always be consistent.
|
|
216
|
+
__classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").clear();
|
|
217
|
+
__classPrivateFieldGet(this, _SnapKeyring_accountIndex, "f").clear();
|
|
218
|
+
// Rebuild per-snap wrappers. Migrations run inside wrapper.deserialize().
|
|
219
|
+
for (const [snapId, accounts] of bySnap) {
|
|
220
|
+
const wrapper = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_getOrCreateKeyringV2).call(this, snapId);
|
|
221
|
+
wrapper.deserialize({ snapId, accounts });
|
|
222
|
+
// onRegister callbacks fired above have repopulated #accountIndex.
|
|
203
223
|
}
|
|
204
|
-
__classPrivateFieldSet(this, _SnapKeyring_accounts, SnapIdMap_1.SnapIdMap.fromObject(accounts), "f");
|
|
205
224
|
}
|
|
206
225
|
/**
|
|
207
226
|
* Get the addresses of the accounts in this keyring.
|
|
@@ -209,7 +228,13 @@ class SnapKeyring {
|
|
|
209
228
|
* @returns The addresses of the accounts in this keyring.
|
|
210
229
|
*/
|
|
211
230
|
async getAccounts() {
|
|
212
|
-
|
|
231
|
+
const addresses = [];
|
|
232
|
+
for (const wrapper of __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").values()) {
|
|
233
|
+
for (const account of wrapper.accounts()) {
|
|
234
|
+
addresses.push(normalizeAccountAddress(account));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return (0, util_1.unique)(addresses);
|
|
213
238
|
}
|
|
214
239
|
/**
|
|
215
240
|
* Get the addresses of the accounts associated with a given Snap.
|
|
@@ -218,9 +243,7 @@ class SnapKeyring {
|
|
|
218
243
|
* @returns The addresses of the accounts associated with the given Snap.
|
|
219
244
|
*/
|
|
220
245
|
async getAccountsBySnapId(snapId) {
|
|
221
|
-
return (0, util_1.unique)(
|
|
222
|
-
.filter(({ snapId: accountSnapId }) => accountSnapId === snapId)
|
|
223
|
-
.map(({ account }) => normalizeAccountAddress(account)));
|
|
246
|
+
return (0, util_1.unique)((__classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").get(snapId)?.accounts() ?? []).map(normalizeAccountAddress));
|
|
224
247
|
}
|
|
225
248
|
/**
|
|
226
249
|
* Create an account.
|
|
@@ -307,7 +330,7 @@ class SnapKeyring {
|
|
|
307
330
|
account = existingAccount;
|
|
308
331
|
}
|
|
309
332
|
else {
|
|
310
|
-
await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_assertAccountCanBeUsed).call(this,
|
|
333
|
+
await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_assertAccountCanBeUsed).call(this, account);
|
|
311
334
|
// Also check for transient accounts that are not yet part of the keyring
|
|
312
335
|
// state.
|
|
313
336
|
if (accountAddresses.has(address) || accountIds.has(account.id)) {
|
|
@@ -324,8 +347,9 @@ class SnapKeyring {
|
|
|
324
347
|
}
|
|
325
348
|
// We update the keyring state only if needed.
|
|
326
349
|
if (newAccounts.length > 0) {
|
|
350
|
+
const wrapper = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_getOrCreateKeyringV2).call(this, snapId);
|
|
327
351
|
for (const account of newAccounts) {
|
|
328
|
-
|
|
352
|
+
wrapper.setAccount(account);
|
|
329
353
|
}
|
|
330
354
|
// NOTE: We assume this will never fail, thus, we don't need to rollback the
|
|
331
355
|
// keyring state if anything goes wrong here.
|
|
@@ -352,7 +376,8 @@ class SnapKeyring {
|
|
|
352
376
|
* @returns `true` if the Snap ID is known, `false` otherwise.
|
|
353
377
|
*/
|
|
354
378
|
hasSnapId(snapId) {
|
|
355
|
-
|
|
379
|
+
const wrapper = __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").get(snapId);
|
|
380
|
+
return wrapper !== undefined && wrapper.accounts().length > 0;
|
|
356
381
|
}
|
|
357
382
|
/**
|
|
358
383
|
* Resolve the Snap account's address associated from a signing request.
|
|
@@ -607,11 +632,13 @@ class SnapKeyring {
|
|
|
607
632
|
* @returns An internal account object for the given address.
|
|
608
633
|
*/
|
|
609
634
|
getAccountByAddress(address) {
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
635
|
+
for (const wrapper of __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").values()) {
|
|
636
|
+
const account = wrapper.lookupByAddress(address);
|
|
637
|
+
if (account) {
|
|
638
|
+
return __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_transformToInternalAccount).call(this, account, wrapper.snapId);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
return undefined;
|
|
615
642
|
}
|
|
616
643
|
/**
|
|
617
644
|
* List all Snap keyring accounts.
|
|
@@ -621,11 +648,17 @@ class SnapKeyring {
|
|
|
621
648
|
* @returns An array containing all Snap keyring accounts.
|
|
622
649
|
*/
|
|
623
650
|
listAccounts() {
|
|
624
|
-
|
|
651
|
+
const accounts = [];
|
|
652
|
+
for (const wrapper of __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").values()) {
|
|
653
|
+
for (const account of wrapper.accounts()) {
|
|
654
|
+
accounts.push(__classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_transformToInternalAccount).call(this, account, wrapper.snapId));
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return accounts;
|
|
625
658
|
}
|
|
626
659
|
}
|
|
627
660
|
exports.SnapKeyring = SnapKeyring;
|
|
628
|
-
_SnapKeyring_messenger = new WeakMap(), _SnapKeyring_snapClient = new WeakMap(),
|
|
661
|
+
_SnapKeyring_messenger = new WeakMap(), _SnapKeyring_snapClient = new WeakMap(), _SnapKeyring_snapKeyrings = new WeakMap(), _SnapKeyring_accountIndex = new WeakMap(), _SnapKeyring_selectedAccounts = new WeakMap(), _SnapKeyring_requests = new WeakMap(), _SnapKeyring_options = new WeakMap(), _SnapKeyring_callbacks = new WeakMap(), _SnapKeyring_isAnyAccountTypeAllowed = new WeakMap(), _SnapKeyring_lock = new WeakMap(), _SnapKeyring_instances = new WeakSet(), _SnapKeyring_withLock =
|
|
629
662
|
/**
|
|
630
663
|
* Execute an operation behind a lock.
|
|
631
664
|
*
|
|
@@ -634,6 +667,21 @@ _SnapKeyring_messenger = new WeakMap(), _SnapKeyring_snapClient = new WeakMap(),
|
|
|
634
667
|
*/
|
|
635
668
|
async function _SnapKeyring_withLock(callback) {
|
|
636
669
|
return __classPrivateFieldGet(this, _SnapKeyring_lock, "f").runExclusive(callback);
|
|
670
|
+
}, _SnapKeyring_getOrCreateKeyringV2 = function _SnapKeyring_getOrCreateKeyringV2(snapId) {
|
|
671
|
+
let keyring = __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").get(snapId);
|
|
672
|
+
if (!keyring) {
|
|
673
|
+
keyring = new SnapKeyringV2_1.SnapKeyringV2({
|
|
674
|
+
snapId,
|
|
675
|
+
onRegister: (id) => {
|
|
676
|
+
__classPrivateFieldGet(this, _SnapKeyring_accountIndex, "f").set(id, snapId);
|
|
677
|
+
},
|
|
678
|
+
onUnregister: (id) => {
|
|
679
|
+
__classPrivateFieldGet(this, _SnapKeyring_accountIndex, "f").delete(id);
|
|
680
|
+
},
|
|
681
|
+
});
|
|
682
|
+
__classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").set(snapId, keyring);
|
|
683
|
+
}
|
|
684
|
+
return keyring;
|
|
637
685
|
}, _SnapKeyring_isMinimumPlatformVersion = function _SnapKeyring_isMinimumPlatformVersion(snapId, platformVersion) {
|
|
638
686
|
return __classPrivateFieldGet(this, _SnapKeyring_messenger, "f").call('SnapController:isMinimumPlatformVersion', snapId, platformVersion);
|
|
639
687
|
}, _SnapKeyring_assertAccountCanBeUsed =
|
|
@@ -641,11 +689,10 @@ async function _SnapKeyring_withLock(callback) {
|
|
|
641
689
|
* Asserts that an account can be used within the Snap keyring. (e.g. generic accounts, unique
|
|
642
690
|
* addresses, etc...).
|
|
643
691
|
*
|
|
644
|
-
* @param snapId - The account's Snap ID.
|
|
645
692
|
* @param account - The account to check.
|
|
646
693
|
* @throws If the account cannot be used.
|
|
647
694
|
*/
|
|
648
|
-
async function _SnapKeyring_assertAccountCanBeUsed(
|
|
695
|
+
async function _SnapKeyring_assertAccountCanBeUsed(account) {
|
|
649
696
|
const address = normalizeAccountAddress(account);
|
|
650
697
|
// The `AnyAccountType.Account` generic account type is allowed only during
|
|
651
698
|
// development, so we check whether it's allowed before continuing.
|
|
@@ -655,7 +702,8 @@ async function _SnapKeyring_assertAccountCanBeUsed(snapId, account) {
|
|
|
655
702
|
}
|
|
656
703
|
// A Snap could try to create an account with a different address but with
|
|
657
704
|
// an existing ID, so the above test only is not enough.
|
|
658
|
-
|
|
705
|
+
// Account IDs are globally unique across all snaps.
|
|
706
|
+
if (__classPrivateFieldGet(this, _SnapKeyring_accountIndex, "f").has(account.id)) {
|
|
659
707
|
throw new Error(`Account '${account.id}' already exists`);
|
|
660
708
|
}
|
|
661
709
|
// The UI still uses the account address to identify accounts, so we need
|
|
@@ -666,14 +714,15 @@ async function _SnapKeyring_assertAccountCanBeUsed(snapId, account) {
|
|
|
666
714
|
}
|
|
667
715
|
}, _SnapKeyring_getExistingAccount = function _SnapKeyring_getExistingAccount(snapId, account) {
|
|
668
716
|
const address = normalizeAccountAddress(account);
|
|
669
|
-
//
|
|
670
|
-
// and that the right Snap is trying to "create" it again.
|
|
717
|
+
// Account creation is idempotent, so we need to check whether the account
|
|
718
|
+
// already exists and that the right Snap is trying to "create" it again.
|
|
671
719
|
// NOTE: We are not checking account object equality here. If a Snap
|
|
672
|
-
// re-
|
|
673
|
-
const
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
720
|
+
// re-sends this event with different account data, we will ignore it.
|
|
721
|
+
const wrapper = __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").get(snapId);
|
|
722
|
+
const existing = wrapper?.lookupAccount(account.id);
|
|
723
|
+
if (existing !== undefined &&
|
|
724
|
+
normalizeAccountAddress(existing) === address) {
|
|
725
|
+
return existing;
|
|
677
726
|
}
|
|
678
727
|
return undefined; // Not a known account.
|
|
679
728
|
}, _SnapKeyring_getInternalOptions = function _SnapKeyring_getInternalOptions(snapId, correlationId) {
|
|
@@ -716,7 +765,7 @@ async function _SnapKeyring_handleAccountCreated(snapId, message) {
|
|
|
716
765
|
return null;
|
|
717
766
|
}
|
|
718
767
|
// Make sure this new account is valid.
|
|
719
|
-
await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_assertAccountCanBeUsed).call(this,
|
|
768
|
+
await __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_assertAccountCanBeUsed).call(this, account);
|
|
720
769
|
// A deferred promise that will be resolved once the Snap keyring has saved
|
|
721
770
|
// its internal state.
|
|
722
771
|
// This part of the flow is run asynchronously, so we have no other way of
|
|
@@ -737,7 +786,7 @@ async function _SnapKeyring_handleAccountCreated(snapId, message) {
|
|
|
737
786
|
//
|
|
738
787
|
// e.g The account creation dialog crashed on MetaMask, this callback
|
|
739
788
|
// will never be called, but the Snap still has the account.
|
|
740
|
-
__classPrivateFieldGet(this,
|
|
789
|
+
__classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_getOrCreateKeyringV2).call(this, snapId).setAccount(account);
|
|
741
790
|
// This is the "true async part". We do not `await` for this call, mainly
|
|
742
791
|
// because this callback will persist the account on the client side
|
|
743
792
|
// (through the `AccountsController`).
|
|
@@ -786,7 +835,8 @@ async function _SnapKeyring_handleAccountCreated(snapId, message) {
|
|
|
786
835
|
async function _SnapKeyring_handleAccountUpdated(snapId, message) {
|
|
787
836
|
(0, superstruct_1.assert)(message, events_1.AccountUpdatedEventStruct);
|
|
788
837
|
const { account: newAccountFromEvent } = message.params;
|
|
789
|
-
const
|
|
838
|
+
const wrapper = __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").get(snapId);
|
|
839
|
+
const oldAccount = wrapper?.lookupAccount(newAccountFromEvent.id) ??
|
|
790
840
|
(0, util_1.throwError)(`Account '${newAccountFromEvent.id}' not found`);
|
|
791
841
|
// Potentially migrate the account.
|
|
792
842
|
const newAccount = (0, account_1.transformAccount)(newAccountFromEvent);
|
|
@@ -806,7 +856,7 @@ async function _SnapKeyring_handleAccountUpdated(snapId, message) {
|
|
|
806
856
|
if (!(0, util_1.equalsIgnoreCase)(oldAccount.address, newAccount.address)) {
|
|
807
857
|
throw new Error(`Cannot change address of account '${newAccount.id}'`);
|
|
808
858
|
}
|
|
809
|
-
__classPrivateFieldGet(this,
|
|
859
|
+
__classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_getOrCreateKeyringV2).call(this, snapId).setAccount(newAccount);
|
|
810
860
|
await __classPrivateFieldGet(this, _SnapKeyring_callbacks, "f").saveState();
|
|
811
861
|
return null;
|
|
812
862
|
}, _SnapKeyring_handleAccountDeleted =
|
|
@@ -820,18 +870,15 @@ async function _SnapKeyring_handleAccountUpdated(snapId, message) {
|
|
|
820
870
|
async function _SnapKeyring_handleAccountDeleted(snapId, message) {
|
|
821
871
|
(0, superstruct_1.assert)(message, events_1.AccountDeletedEventStruct);
|
|
822
872
|
const { id } = message.params;
|
|
823
|
-
const
|
|
873
|
+
const account = __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").get(snapId)?.lookupAccount(id);
|
|
824
874
|
// We can ignore the case where the account was already removed from the
|
|
825
875
|
// keyring, making the deletion idempotent.
|
|
826
876
|
//
|
|
827
877
|
// This happens when the keyring calls the Snap to delete an account, and
|
|
828
878
|
// the Snap calls the keyring back with an `AccountDeleted` event.
|
|
829
|
-
if (
|
|
879
|
+
if (account === undefined) {
|
|
830
880
|
return null;
|
|
831
881
|
}
|
|
832
|
-
// At this point we know that the account exists, so we can safely
|
|
833
|
-
// destructure it.
|
|
834
|
-
const { account } = entry;
|
|
835
882
|
await __classPrivateFieldGet(this, _SnapKeyring_callbacks, "f").removeAccount(normalizeAccountAddress(account), snapId, async (accepted) => {
|
|
836
883
|
if (accepted) {
|
|
837
884
|
await __classPrivateFieldGet(this, _SnapKeyring_callbacks, "f").saveState();
|
|
@@ -895,7 +942,7 @@ async function _SnapKeyring_rePublishAccountEvent(snapId, event, filteredEventCa
|
|
|
895
942
|
// prevent other Snaps from updating accounts they do not own.
|
|
896
943
|
const filter = (accountMapping) => {
|
|
897
944
|
return Object.entries(accountMapping).reduce((filtered, [accountId, entry]) => {
|
|
898
|
-
if (__classPrivateFieldGet(this,
|
|
945
|
+
if (__classPrivateFieldGet(this, _SnapKeyring_accountIndex, "f").get(accountId) === snapId) {
|
|
899
946
|
// If the Snap owns this account, we can use it.
|
|
900
947
|
filtered[accountId] = entry;
|
|
901
948
|
}
|
|
@@ -954,11 +1001,14 @@ async function _SnapKeyring_handleAccountTransactionsUpdated(snapId, message) {
|
|
|
954
1001
|
return [event];
|
|
955
1002
|
});
|
|
956
1003
|
}, _SnapKeyring_getAccount = function _SnapKeyring_getAccount(id) {
|
|
957
|
-
const
|
|
958
|
-
|
|
1004
|
+
const snapId = __classPrivateFieldGet(this, _SnapKeyring_accountIndex, "f").get(id);
|
|
1005
|
+
const account = snapId
|
|
1006
|
+
? __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").get(snapId)?.lookupAccount(id)
|
|
1007
|
+
: undefined;
|
|
1008
|
+
if (!snapId || !account) {
|
|
959
1009
|
throw new Error(`Unable to get account: unknown account ID: '${id}'`);
|
|
960
1010
|
}
|
|
961
|
-
return
|
|
1011
|
+
return { account, snapId };
|
|
962
1012
|
}, _SnapKeyring_submitRequest =
|
|
963
1013
|
/**
|
|
964
1014
|
* Submit a request to a Snap from an account address.
|
|
@@ -1113,8 +1163,8 @@ async function _SnapKeyring_handleAsyncResponse(redirect, snapId) {
|
|
|
1113
1163
|
*/
|
|
1114
1164
|
async function _SnapKeyring_deleteAccount(snapId, account) {
|
|
1115
1165
|
// Always remove the account from the maps, even if the Snap is going to
|
|
1116
|
-
// fail to delete it.
|
|
1117
|
-
__classPrivateFieldGet(this,
|
|
1166
|
+
// fail to delete it. removeAccount fires onUnregister to clean #accountIndex.
|
|
1167
|
+
__classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").get(snapId)?.removeAccount(account.id);
|
|
1118
1168
|
try {
|
|
1119
1169
|
await __classPrivateFieldGet(this, _SnapKeyring_snapClient, "f").withSnapId(snapId).deleteAccount(account.id);
|
|
1120
1170
|
}
|
|
@@ -1125,12 +1175,18 @@ async function _SnapKeyring_deleteAccount(snapId, account) {
|
|
|
1125
1175
|
console.error(`Account '${account.address}' may not have been removed from snap '${snapId}':`, error);
|
|
1126
1176
|
}
|
|
1127
1177
|
}, _SnapKeyring_resolveAddress = function _SnapKeyring_resolveAddress(address) {
|
|
1128
|
-
|
|
1178
|
+
for (const wrapper of __classPrivateFieldGet(this, _SnapKeyring_snapKeyrings, "f").values()) {
|
|
1179
|
+
const account = wrapper.lookupByAddress(address);
|
|
1180
|
+
if (account) {
|
|
1181
|
+
return { account, snapId: wrapper.snapId };
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
return (0, util_1.throwError)(`Account '${address}' not found`);
|
|
1129
1185
|
}, _SnapKeyring_updateSelectedAccountsMap = function _SnapKeyring_updateSelectedAccountsMap(accounts) {
|
|
1130
1186
|
const selectedAccounts = __classPrivateFieldGet(this, _SnapKeyring_selectedAccounts, "f");
|
|
1131
1187
|
selectedAccounts.clear();
|
|
1132
1188
|
for (const account of accounts) {
|
|
1133
|
-
const snapId = __classPrivateFieldGet(this,
|
|
1189
|
+
const snapId = __classPrivateFieldGet(this, _SnapKeyring_accountIndex, "f").get(account);
|
|
1134
1190
|
if (!snapId) {
|
|
1135
1191
|
continue;
|
|
1136
1192
|
}
|
|
@@ -1139,7 +1195,7 @@ async function _SnapKeyring_deleteAccount(snapId, account) {
|
|
|
1139
1195
|
selectedAccounts.set(snapId, snapAccounts);
|
|
1140
1196
|
}
|
|
1141
1197
|
}, _SnapKeyring_getSnap = function _SnapKeyring_getSnap(snapId) {
|
|
1142
|
-
return __classPrivateFieldGet(this, _SnapKeyring_messenger, "f").call('SnapController:
|
|
1198
|
+
return __classPrivateFieldGet(this, _SnapKeyring_messenger, "f").call('SnapController:getSnap', snapId);
|
|
1143
1199
|
}, _SnapKeyring_getSnapMetadata = function _SnapKeyring_getSnapMetadata(snapId) {
|
|
1144
1200
|
const snap = __classPrivateFieldGet(this, _SnapKeyring_instances, "m", _SnapKeyring_getSnap).call(this, snapId);
|
|
1145
1201
|
return snap
|