@metamask/multichain-account-service 11.0.0 → 12.0.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.
Files changed (106) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/dist/MultichainAccountGroup.cjs +15 -2
  3. package/dist/MultichainAccountGroup.cjs.map +1 -1
  4. package/dist/MultichainAccountGroup.d.cts +11 -0
  5. package/dist/MultichainAccountGroup.d.cts.map +1 -1
  6. package/dist/MultichainAccountGroup.d.mts +11 -0
  7. package/dist/MultichainAccountGroup.d.mts.map +1 -1
  8. package/dist/MultichainAccountGroup.mjs +15 -2
  9. package/dist/MultichainAccountGroup.mjs.map +1 -1
  10. package/dist/MultichainAccountWallet.cjs +45 -21
  11. package/dist/MultichainAccountWallet.cjs.map +1 -1
  12. package/dist/MultichainAccountWallet.d.cts.map +1 -1
  13. package/dist/MultichainAccountWallet.d.mts.map +1 -1
  14. package/dist/MultichainAccountWallet.mjs +45 -21
  15. package/dist/MultichainAccountWallet.mjs.map +1 -1
  16. package/dist/index.cjs +3 -1
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +1 -1
  19. package/dist/index.d.cts.map +1 -1
  20. package/dist/index.d.mts +1 -1
  21. package/dist/index.d.mts.map +1 -1
  22. package/dist/index.mjs +1 -1
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/providers/BtcAccountProvider.cjs +7 -38
  25. package/dist/providers/BtcAccountProvider.cjs.map +1 -1
  26. package/dist/providers/BtcAccountProvider.d.cts +2 -6
  27. package/dist/providers/BtcAccountProvider.d.cts.map +1 -1
  28. package/dist/providers/BtcAccountProvider.d.mts +2 -6
  29. package/dist/providers/BtcAccountProvider.d.mts.map +1 -1
  30. package/dist/providers/BtcAccountProvider.mjs +8 -39
  31. package/dist/providers/BtcAccountProvider.mjs.map +1 -1
  32. package/dist/providers/SnapAccountProvider.cjs +125 -27
  33. package/dist/providers/SnapAccountProvider.cjs.map +1 -1
  34. package/dist/providers/SnapAccountProvider.d.cts +59 -15
  35. package/dist/providers/SnapAccountProvider.d.cts.map +1 -1
  36. package/dist/providers/SnapAccountProvider.d.mts +59 -15
  37. package/dist/providers/SnapAccountProvider.d.mts.map +1 -1
  38. package/dist/providers/SnapAccountProvider.mjs +127 -29
  39. package/dist/providers/SnapAccountProvider.mjs.map +1 -1
  40. package/dist/providers/SnapKeyringClient.cjs +35 -0
  41. package/dist/providers/SnapKeyringClient.cjs.map +1 -0
  42. package/dist/providers/SnapKeyringClient.d.cts +51 -0
  43. package/dist/providers/SnapKeyringClient.d.cts.map +1 -0
  44. package/dist/providers/SnapKeyringClient.d.mts +51 -0
  45. package/dist/providers/SnapKeyringClient.d.mts.map +1 -0
  46. package/dist/providers/SnapKeyringClient.mjs +31 -0
  47. package/dist/providers/SnapKeyringClient.mjs.map +1 -0
  48. package/dist/providers/SolAccountProvider.cjs +7 -40
  49. package/dist/providers/SolAccountProvider.cjs.map +1 -1
  50. package/dist/providers/SolAccountProvider.d.cts +2 -6
  51. package/dist/providers/SolAccountProvider.d.cts.map +1 -1
  52. package/dist/providers/SolAccountProvider.d.mts +2 -6
  53. package/dist/providers/SolAccountProvider.d.mts.map +1 -1
  54. package/dist/providers/SolAccountProvider.mjs +8 -41
  55. package/dist/providers/SolAccountProvider.mjs.map +1 -1
  56. package/dist/providers/TrxAccountProvider.cjs +7 -37
  57. package/dist/providers/TrxAccountProvider.cjs.map +1 -1
  58. package/dist/providers/TrxAccountProvider.d.cts +2 -6
  59. package/dist/providers/TrxAccountProvider.d.cts.map +1 -1
  60. package/dist/providers/TrxAccountProvider.d.mts +2 -6
  61. package/dist/providers/TrxAccountProvider.d.mts.map +1 -1
  62. package/dist/providers/TrxAccountProvider.mjs +8 -38
  63. package/dist/providers/TrxAccountProvider.mjs.map +1 -1
  64. package/dist/providers/XlmAccountProvider.cjs +53 -0
  65. package/dist/providers/XlmAccountProvider.cjs.map +1 -0
  66. package/dist/providers/XlmAccountProvider.d.cts +25 -0
  67. package/dist/providers/XlmAccountProvider.d.cts.map +1 -0
  68. package/dist/providers/XlmAccountProvider.d.mts +25 -0
  69. package/dist/providers/XlmAccountProvider.d.mts.map +1 -0
  70. package/dist/providers/XlmAccountProvider.mjs +49 -0
  71. package/dist/providers/XlmAccountProvider.mjs.map +1 -0
  72. package/dist/providers/index.cjs +1 -0
  73. package/dist/providers/index.cjs.map +1 -1
  74. package/dist/providers/index.d.cts +1 -0
  75. package/dist/providers/index.d.cts.map +1 -1
  76. package/dist/providers/index.d.mts +1 -0
  77. package/dist/providers/index.d.mts.map +1 -1
  78. package/dist/providers/index.mjs +1 -0
  79. package/dist/providers/index.mjs.map +1 -1
  80. package/dist/tests/accounts.cjs +29 -1
  81. package/dist/tests/accounts.cjs.map +1 -1
  82. package/dist/tests/accounts.d.cts +2 -0
  83. package/dist/tests/accounts.d.cts.map +1 -1
  84. package/dist/tests/accounts.d.mts +2 -0
  85. package/dist/tests/accounts.d.mts.map +1 -1
  86. package/dist/tests/accounts.mjs +29 -1
  87. package/dist/tests/accounts.mjs.map +1 -1
  88. package/dist/tests/messenger.cjs +1 -0
  89. package/dist/tests/messenger.cjs.map +1 -1
  90. package/dist/tests/messenger.d.cts.map +1 -1
  91. package/dist/tests/messenger.d.mts.map +1 -1
  92. package/dist/tests/messenger.mjs +1 -0
  93. package/dist/tests/messenger.mjs.map +1 -1
  94. package/dist/tests/providers.cjs +1 -0
  95. package/dist/tests/providers.cjs.map +1 -1
  96. package/dist/tests/providers.d.cts.map +1 -1
  97. package/dist/tests/providers.d.mts.map +1 -1
  98. package/dist/tests/providers.mjs +2 -1
  99. package/dist/tests/providers.mjs.map +1 -1
  100. package/dist/types.cjs.map +1 -1
  101. package/dist/types.d.cts +2 -2
  102. package/dist/types.d.cts.map +1 -1
  103. package/dist/types.d.mts +2 -2
  104. package/dist/types.d.mts.map +1 -1
  105. package/dist/types.mjs.map +1 -1
  106. package/package.json +8 -8
@@ -1,14 +1,27 @@
1
1
  import type { Bip44Account } from "@metamask/account-api";
2
2
  import type { TraceCallback, TraceRequest } from "@metamask/controller-utils";
3
+ import type { SnapKeyringV1 } from "@metamask/eth-snap-keyring";
3
4
  import type { SnapKeyring as SnapKeyringV2 } from "@metamask/eth-snap-keyring/v2";
4
- import type { CreateAccountBip44DeriveIndexOptions, CreateAccountBip44DeriveIndexRangeOptions, CreateAccountOptions, EntropySourceId, KeyringAccount } from "@metamask/keyring-api";
5
+ import type { CreateAccountBip44DeriveIndexOptions, CreateAccountBip44DeriveIndexRangeOptions, CreateAccountBip44DiscoverOptions, CreateAccountOptions, EntropySourceId, KeyringAccount } from "@metamask/keyring-api";
6
+ import type { KeyringCapabilities } from "@metamask/keyring-api/v2";
5
7
  import type { InternalAccount } from "@metamask/keyring-internal-api";
6
- import { KeyringClient } from "@metamask/keyring-snap-client";
7
8
  import type { SnapId } from "@metamask/snaps-sdk";
9
+ import type { CaipChainId } from "@metamask/utils";
8
10
  import type { MultichainAccountServiceMessenger } from "../types.mjs";
9
11
  import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.mjs";
12
+ import type { SnapKeyringClient } from "./SnapKeyringClient.mjs";
10
13
  export type RestrictedSnapKeyring = {
11
- createAccount: SnapKeyringV2['createAccount'];
14
+ /**
15
+ * V1 interface, present only when the Snap does not declare v2 capabilities.
16
+ * `undefined` for v2-only Snaps.
17
+ *
18
+ * Use this to make v1 calls explicit:
19
+ * if (!keyring.v1) { throw new Error('Snap is v2-only'); }
20
+ * keyring.v1.createAccount(options);
21
+ */
22
+ v1?: {
23
+ createAccount: SnapKeyringV1['createAccount'];
24
+ };
12
25
  createAccounts: SnapKeyringV2['createAccounts'];
13
26
  deleteAccount: SnapKeyringV2['deleteAccount'];
14
27
  };
@@ -21,18 +34,12 @@ export type SnapAccountProviderConfig = {
21
34
  backOffMs: number;
22
35
  };
23
36
  createAccounts: {
24
- /**
25
- * Whether to enable account batching with `createAccounts` method. If `true`, accounts will
26
- * be created in batch.
27
- *
28
- * NOTE: The Snap has to implement this optional method for batching support.
29
- * Defaults to `false`.
30
- */
31
- batched: boolean;
32
37
  /**
33
38
  * Timeout for account creation operations.
34
39
  *
35
- * NOTE: The value might have to be adapted in case batching is enabled!
40
+ * NOTE: Batching (and thus whether a single call may create multiple
41
+ * accounts) is driven by the Snap's declared capabilities, not this config.
42
+ * The value might have to be adapted when the Snap supports batching.
36
43
  */
37
44
  timeoutMs: number;
38
45
  };
@@ -49,6 +56,20 @@ export declare abstract class SnapAccountProvider extends BaseBip44AccountProvid
49
56
  #private;
50
57
  readonly snapId: SnapId;
51
58
  protected readonly config: SnapAccountProviderConfig;
59
+ /**
60
+ * The Snap's keyring capabilities, sourced from `SnapAccountService` (which
61
+ * reads them from the Snap's manifest). Populated the first time the client
62
+ * is resolved; defaults to an empty capability set until then.
63
+ */
64
+ capabilities: KeyringCapabilities;
65
+ /**
66
+ * Scopes passed to the v1 `discoverAccounts` client method. Only used on the
67
+ * v1 discovery path.
68
+ *
69
+ * TODO: Remove once all Snaps are fully v2 — discovery is then driven by the
70
+ * Snap's own supported scopes via `createAccounts({ bip44:discover })`.
71
+ */
72
+ protected abstract readonly v1DiscoveryScopes: CaipChainId[];
52
73
  constructor(snapId: SnapId, messenger: MultichainAccountServiceMessenger, config: SnapAccountProviderConfig, trace?: TraceCallback);
53
74
  /**
54
75
  * Ensures that the Snap is ready to be used.
@@ -67,9 +88,16 @@ export declare abstract class SnapAccountProvider extends BaseBip44AccountProvid
67
88
  */
68
89
  protected withMaxConcurrency<Result>(operation: () => Promise<Result>): Promise<Result>;
69
90
  protected trace<ReturnType>(request: TraceRequest, fn: () => Promise<ReturnType>): Promise<ReturnType>;
91
+ /**
92
+ * Whether the Snap supports the v2 keyring protocol, inferred from its
93
+ * declared capabilities (a v2-capable Snap declares BIP-44 capabilities).
94
+ *
95
+ * @returns `true` if the Snap is v2-capable.
96
+ */
97
+ protected isV2(): boolean;
70
98
  resyncAccounts(accounts: Bip44Account<InternalAccount>[]): Promise<void>;
71
99
  protected withSnap<CallbackResult = void>(operation: (snap: {
72
- client: KeyringClient;
100
+ client: SnapKeyringClient;
73
101
  keyring: RestrictedSnapKeyring;
74
102
  }) => Promise<CallbackResult>): Promise<CallbackResult>;
75
103
  abstract isAccountCompatible(account: Bip44Account<InternalAccount>): boolean;
@@ -81,7 +109,7 @@ export declare abstract class SnapAccountProvider extends BaseBip44AccountProvid
81
109
  entropySource: EntropySourceId;
82
110
  groupIndex: number;
83
111
  }): Bip44Account<KeyringAccount>;
84
- protected createBip44Accounts(keyring: RestrictedSnapKeyring, options: CreateAccountBip44DeriveIndexOptions | CreateAccountBip44DeriveIndexRangeOptions): Promise<Bip44Account<KeyringAccount>[]>;
112
+ protected createBip44Accounts(keyring: RestrictedSnapKeyring, options: CreateAccountBip44DeriveIndexOptions | CreateAccountBip44DeriveIndexRangeOptions | CreateAccountBip44DiscoverOptions): Promise<Bip44Account<KeyringAccount>[]>;
85
113
  createAccounts(options: CreateAccountOptions): Promise<Bip44Account<KeyringAccount>[]>;
86
114
  /**
87
115
  * Delete a snap account by id.
@@ -94,7 +122,23 @@ export declare abstract class SnapAccountProvider extends BaseBip44AccountProvid
94
122
  * @param id - The id of the account to delete.
95
123
  */
96
124
  deleteAccount(id: Bip44Account<KeyringAccount>['id']): Promise<void>;
97
- abstract discoverAccounts(options: {
125
+ /**
126
+ * Discovers accounts for the given entropy source and group index.
127
+ *
128
+ * v2 Snaps drive discovery through `createAccounts({ bip44:discover })`: the
129
+ * Snap checks for on-chain activity (using its own supported scopes) and
130
+ * returns the created account(s), or nothing once discovery is exhausted.
131
+ *
132
+ * v1 Snaps use the client's `discoverAccounts` to detect activity on
133
+ * {@link v1DiscoveryScopes}, then create the account for the group index.
134
+ *
135
+ * @param options - The discovery options.
136
+ * @param options.entropySource - The entropy source to discover accounts for.
137
+ * @param options.groupIndex - The group index to discover accounts for.
138
+ * @returns The discovered (and created) accounts, or an empty array when
139
+ * there is nothing to discover at this group index.
140
+ */
141
+ discoverAccounts({ entropySource, groupIndex, }: {
98
142
  entropySource: EntropySourceId;
99
143
  groupIndex: number;
100
144
  }): Promise<Bip44Account<KeyringAccount>[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SnapAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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"}
@@ -9,29 +9,40 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
- var _SnapAccountProvider_instances, _SnapAccountProvider_client, _SnapAccountProvider_queue, _SnapAccountProvider_trace, _SnapAccountProvider_getRestrictedSnapKeyring, _SnapAccountProvider_getKeyringClientFromSnapId, _SnapAccountProvider_withSnapKeyring;
12
+ var _SnapAccountProvider_instances, _SnapAccountProvider_client, _SnapAccountProvider_sender, _SnapAccountProvider_queue, _SnapAccountProvider_trace, _SnapAccountProvider_getRestrictedSnapKeyring, _SnapAccountProvider_createSender, _SnapAccountProvider_resolveClient, _SnapAccountProvider_withSnapKeyring;
13
13
  import { assertIsBip44Account } from "@metamask/account-api";
14
- import { isSnapKeyring } from "@metamask/eth-snap-keyring/v2";
14
+ import { EMPTY_CAPABILITIES, isSnapKeyring } from "@metamask/eth-snap-keyring/v2";
15
15
  import { AccountCreationType, assertCreateAccountOptionIsSupported } from "@metamask/keyring-api";
16
- import { KeyringClient } from "@metamask/keyring-snap-client";
17
16
  import { HandlerType } from "@metamask/snaps-utils";
18
17
  import { Semaphore } from "async-mutex";
19
18
  import { toCreateAccountsV2DataTraces, traceFallback, TraceName } from "../analytics/index.mjs";
20
19
  import { reportError } from "../errors.mjs";
21
20
  import { projectLogger as log, WARNING_PREFIX } from "../logger.mjs";
22
21
  import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.mjs";
23
- import { withTimeout } from "./utils.mjs";
22
+ import { createSnapKeyringClient } from "./SnapKeyringClient.mjs";
23
+ import { withRetry, withTimeout } from "./utils.mjs";
24
24
  export class SnapAccountProvider extends BaseBip44AccountProvider {
25
25
  constructor(snapId, messenger, config,
26
26
  /* istanbul ignore next */
27
27
  trace = traceFallback) {
28
28
  super(messenger);
29
29
  _SnapAccountProvider_instances.add(this);
30
+ /**
31
+ * The Snap's keyring capabilities, sourced from `SnapAccountService` (which
32
+ * reads them from the Snap's manifest). Populated the first time the client
33
+ * is resolved; defaults to an empty capability set until then.
34
+ */
35
+ this.capabilities = EMPTY_CAPABILITIES;
36
+ /**
37
+ * Version-agnostic keyring client, resolved lazily once the Snap is ready and
38
+ * its capabilities are known — see {@link SnapAccountProvider.withSnap}.
39
+ */
30
40
  _SnapAccountProvider_client.set(this, void 0);
41
+ _SnapAccountProvider_sender.set(this, void 0);
31
42
  _SnapAccountProvider_queue.set(this, void 0);
32
43
  _SnapAccountProvider_trace.set(this, void 0);
33
44
  this.snapId = snapId;
34
- __classPrivateFieldSet(this, _SnapAccountProvider_client, __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_getKeyringClientFromSnapId).call(this, snapId), "f");
45
+ __classPrivateFieldSet(this, _SnapAccountProvider_sender, __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_createSender).call(this, snapId), "f");
35
46
  const maxConcurrency = config.maxConcurrency ?? Infinity;
36
47
  this.config = {
37
48
  ...config,
@@ -73,10 +84,19 @@ export class SnapAccountProvider extends BaseBip44AccountProvider {
73
84
  async trace(request, fn) {
74
85
  return __classPrivateFieldGet(this, _SnapAccountProvider_trace, "f").call(this, request, fn);
75
86
  }
87
+ /**
88
+ * Whether the Snap supports the v2 keyring protocol, inferred from its
89
+ * declared capabilities (a v2-capable Snap declares BIP-44 capabilities).
90
+ *
91
+ * @returns `true` if the Snap is v2-capable.
92
+ */
93
+ isV2() {
94
+ return Boolean(this.capabilities.bip44);
95
+ }
76
96
  async resyncAccounts(accounts) {
77
- await this.withSnap(async ({ keyring }) => {
97
+ await this.withSnap(async ({ client, keyring }) => {
78
98
  const localSnapAccounts = accounts.filter((account) => account.metadata.snap?.id === this.snapId);
79
- const snapAccounts = new Set((await __classPrivateFieldGet(this, _SnapAccountProvider_client, "f").listAccounts()).map((account) => account.id));
99
+ const snapAccounts = new Set((await client.getAccounts()).map((account) => account.id));
80
100
  // NOTE: This should never happen, but if it does, we recover by deleting the
81
101
  // extra accounts from the Snap to bring it back in sync with MetaMask.
82
102
  if (localSnapAccounts.length < snapAccounts.size) {
@@ -90,7 +110,7 @@ export class SnapAccountProvider extends BaseBip44AccountProvider {
90
110
  if (!localAccountIds.has(snapAccountId)) {
91
111
  // This account exists in the Snap but not in MetaMask, delete it from
92
112
  // the Snap.
93
- await __classPrivateFieldGet(this, _SnapAccountProvider_client, "f").deleteAccount(snapAccountId);
113
+ await client.deleteAccount(snapAccountId);
94
114
  // Update the local Set so subsequent checks use the correct size
95
115
  snapAccounts.delete(snapAccountId);
96
116
  }
@@ -142,8 +162,9 @@ export class SnapAccountProvider extends BaseBip44AccountProvider {
142
162
  }
143
163
  async withSnap(operation) {
144
164
  await this.ensureReady();
165
+ const client = await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_resolveClient).call(this);
145
166
  return await operation({
146
- client: __classPrivateFieldGet(this, _SnapAccountProvider_client, "f"),
167
+ client,
147
168
  keyring: await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_getRestrictedSnapKeyring).call(this),
148
169
  });
149
170
  }
@@ -155,7 +176,10 @@ export class SnapAccountProvider extends BaseBip44AccountProvider {
155
176
  return this.withMaxConcurrency(async () => {
156
177
  let groupIndexOffset = 0;
157
178
  let snapAccounts = [];
158
- const batched = this.config.createAccounts.batched ?? false;
179
+ // v2 Snaps expose `createAccounts` but no singular `createAccount`, so
180
+ // they must always go through the batched flow. v1 Snaps only have the
181
+ // singular `createAccount`.
182
+ const batched = this.isV2();
159
183
  const { entropySource } = options;
160
184
  const createAccountV1 = async (groupIndex) => await withTimeout(() => this.trace({
161
185
  name: TraceName.ProviderCreateAccountV1,
@@ -237,35 +261,90 @@ export class SnapAccountProvider extends BaseBip44AccountProvider {
237
261
  });
238
262
  this.accounts.delete(id);
239
263
  }
264
+ /**
265
+ * Discovers accounts for the given entropy source and group index.
266
+ *
267
+ * v2 Snaps drive discovery through `createAccounts({ bip44:discover })`: the
268
+ * Snap checks for on-chain activity (using its own supported scopes) and
269
+ * returns the created account(s), or nothing once discovery is exhausted.
270
+ *
271
+ * v1 Snaps use the client's `discoverAccounts` to detect activity on
272
+ * {@link v1DiscoveryScopes}, then create the account for the group index.
273
+ *
274
+ * @param options - The discovery options.
275
+ * @param options.entropySource - The entropy source to discover accounts for.
276
+ * @param options.groupIndex - The group index to discover accounts for.
277
+ * @returns The discovered (and created) accounts, or an empty array when
278
+ * there is nothing to discover at this group index.
279
+ */
280
+ async discoverAccounts({ entropySource, groupIndex, }) {
281
+ return this.withSnap(async ({ client, keyring }) => this.trace({
282
+ name: TraceName.SnapDiscoverAccounts,
283
+ data: {
284
+ provider: this.getName(),
285
+ },
286
+ }, async () => {
287
+ if (!this.config.discovery.enabled) {
288
+ return [];
289
+ }
290
+ if (this.isV2()) {
291
+ // The v2 client has no `discoverAccounts`, so discovery is only
292
+ // possible when the Snap supports `bip44:discover`. Otherwise there
293
+ // is no way to discover and we report nothing.
294
+ if (!this.capabilities.bip44?.discover) {
295
+ return [];
296
+ }
297
+ // v2: the Snap detects on-chain activity and creates the account in
298
+ // a single `createAccounts({ bip44:discover })` call. An empty
299
+ // result means discovery is exhausted at this group index.
300
+ return this.createBip44Accounts(keyring, {
301
+ type: AccountCreationType.Bip44Discover,
302
+ entropySource,
303
+ groupIndex,
304
+ });
305
+ }
306
+ // v1: detect activity via the client, then create the account for
307
+ // this group index.
308
+ const discoveredAccounts = await withRetry(() => withTimeout(() => client.discoverAccounts(this.v1DiscoveryScopes, entropySource, groupIndex), this.config.discovery.timeoutMs), {
309
+ maxAttempts: this.config.discovery.maxAttempts,
310
+ backOffMs: this.config.discovery.backOffMs,
311
+ });
312
+ if (!discoveredAccounts.length) {
313
+ return [];
314
+ }
315
+ return this.createBip44Accounts(keyring, {
316
+ type: AccountCreationType.Bip44DeriveIndex,
317
+ entropySource,
318
+ groupIndex,
319
+ });
320
+ }));
321
+ }
240
322
  }
241
- _SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_queue = new WeakMap(), _SnapAccountProvider_trace = new WeakMap(), _SnapAccountProvider_instances = new WeakSet(), _SnapAccountProvider_getRestrictedSnapKeyring = async function _SnapAccountProvider_getRestrictedSnapKeyring() {
323
+ _SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_sender = new WeakMap(), _SnapAccountProvider_queue = new WeakMap(), _SnapAccountProvider_trace = new WeakMap(), _SnapAccountProvider_instances = new WeakSet(), _SnapAccountProvider_getRestrictedSnapKeyring = async function _SnapAccountProvider_getRestrictedSnapKeyring() {
242
324
  // NOTE: We're not supposed to make the keyring instance escape `withKeyringV2` but
243
325
  // we have to use the `SnapKeyringV2` instance to be able to create Solana account
244
326
  // without triggering UI confirmation.
245
327
  // Also, creating account that way won't invalidate the Snap keyring state. The
246
328
  // account will get created and persisted properly with the Snap account creation
247
329
  // flow "asynchronously" (with `notify:accountCreated`).
248
- const { createAccount, createAccounts } = await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => ({
249
- createAccount: keyring.createAccount.bind(keyring),
250
- createAccounts: keyring.createAccounts.bind(keyring),
251
- }));
330
+ const createAccount = await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => {
331
+ if (keyring.v1) {
332
+ return keyring.v1.createAccount.bind(keyring.v1);
333
+ }
334
+ // This method does not exist in v2.
335
+ return undefined;
336
+ });
252
337
  return {
253
- createAccount: async (options) =>
254
- // We use the "unguarded" account creation here (see explanation above).
255
- await createAccount(options, {
256
- displayAccountNameSuggestion: false,
257
- displayConfirmation: false,
258
- setSelectedAccount: false,
259
- }),
260
- createAccounts: async (options) => await createAccounts(options),
261
- deleteAccount: async (id) =>
262
- // Though, when removing account, we can use the normal flow.
263
- await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => {
338
+ // V1 interface is only present for v1 Snaps, otherwise it's `undefined`.
339
+ v1: createAccount ? { createAccount } : undefined,
340
+ // Every v2 operations must be done through the `#withSnapKeyring` transaction:
341
+ createAccounts: async (options) => await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => await keyring.createAccounts(options)),
342
+ deleteAccount: async (id) => await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => {
264
343
  await keyring.deleteAccount(id);
265
344
  }),
266
345
  };
267
- }, _SnapAccountProvider_getKeyringClientFromSnapId = function _SnapAccountProvider_getKeyringClientFromSnapId(snapId) {
268
- return new KeyringClient({
346
+ }, _SnapAccountProvider_createSender = function _SnapAccountProvider_createSender(snapId) {
347
+ return {
269
348
  send: async (request) => {
270
349
  const response = await this.messenger.call('SnapController:handleRequest', {
271
350
  snapId: snapId,
@@ -275,7 +354,26 @@ _SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_queue = new We
275
354
  });
276
355
  return response;
277
356
  },
278
- });
357
+ };
358
+ }, _SnapAccountProvider_resolveClient =
359
+ /**
360
+ * Resolves the version-agnostic keyring client, fetching the Snap's
361
+ * capabilities from `SnapAccountService` on first use and caching both the
362
+ * capabilities and the resulting client.
363
+ *
364
+ * Callers must ensure the Snap is ready (via
365
+ * {@link SnapAccountProvider.ensureReady}) beforehand so that the
366
+ * capabilities are reliably populated — {@link SnapAccountProvider.withSnap}
367
+ * guarantees this ordering.
368
+ *
369
+ * @returns The resolved {@link SnapKeyringClient}.
370
+ */
371
+ async function _SnapAccountProvider_resolveClient() {
372
+ if (!__classPrivateFieldGet(this, _SnapAccountProvider_client, "f")) {
373
+ this.capabilities = await this.messenger.call('SnapAccountService:getCapabilities', this.snapId);
374
+ __classPrivateFieldSet(this, _SnapAccountProvider_client, createSnapKeyringClient(__classPrivateFieldGet(this, _SnapAccountProvider_sender, "f"), this.isV2()), "f");
375
+ }
376
+ return __classPrivateFieldGet(this, _SnapAccountProvider_client, "f");
279
377
  }, _SnapAccountProvider_withSnapKeyring = async function _SnapAccountProvider_withSnapKeyring(operation) {
280
378
  return this.withKeyringV2({
281
379
  filter: (keyring) => isSnapKeyring(keyring) && keyring.snapId === this.snapId,
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountProvider.mjs","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertIsBip44Account } from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { TraceCallback, TraceRequest } from '@metamask/controller-utils';\nimport type { SnapKeyring as SnapKeyringV2 } from '@metamask/eth-snap-keyring/v2';\nimport { isSnapKeyring } from '@metamask/eth-snap-keyring/v2';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n} from '@metamask/keyring-api';\nimport type {\n CreateAccountBip44DeriveIndexOptions,\n CreateAccountBip44DeriveIndexRangeOptions,\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n} from '@metamask/keyring-api';\nimport type { KeyringMetadata } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Semaphore } from 'async-mutex';\n\nimport {\n toCreateAccountsV2DataTraces,\n traceFallback,\n TraceName,\n} from '../analytics';\nimport { reportError } from '../errors';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\nimport { BaseBip44AccountProvider } from './BaseBip44AccountProvider';\nimport { withTimeout } from './utils';\n\nexport type RestrictedSnapKeyring = {\n createAccount: SnapKeyringV2['createAccount'];\n createAccounts: SnapKeyringV2['createAccounts'];\n deleteAccount: SnapKeyringV2['deleteAccount'];\n};\n\nexport type SnapAccountProviderConfig = {\n maxConcurrency?: number;\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n createAccounts: {\n /**\n * Whether to enable account batching with `createAccounts` method. If `true`, accounts will\n * be created in batch.\n *\n * NOTE: The Snap has to implement this optional method for batching support.\n * Defaults to `false`.\n */\n batched: boolean;\n /**\n * Timeout for account creation operations.\n *\n * NOTE: The value might have to be adapted in case batching is enabled!\n */\n timeoutMs: number;\n };\n resyncAccounts?: {\n /**\n * Whether to automatically remove extra Snap accounts when the Snap has\n * more accounts than MetaMask. If `false`, a warning is logged instead.\n * Defaults to `true`.\n */\n autoRemoveExtraSnapAccounts?: boolean;\n };\n};\n\nexport abstract class SnapAccountProvider extends BaseBip44AccountProvider {\n readonly snapId: SnapId;\n\n protected readonly config: SnapAccountProviderConfig;\n\n readonly #client: KeyringClient;\n\n readonly #queue?: Semaphore;\n\n readonly #trace: TraceCallback;\n\n constructor(\n snapId: SnapId,\n messenger: MultichainAccountServiceMessenger,\n config: SnapAccountProviderConfig,\n /* istanbul ignore next */\n trace: TraceCallback = traceFallback,\n ) {\n super(messenger);\n\n this.snapId = snapId;\n this.#client = this.#getKeyringClientFromSnapId(snapId);\n\n const maxConcurrency = config.maxConcurrency ?? Infinity;\n this.config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n maxConcurrency,\n };\n\n // Create semaphore only if concurrency is limited\n if (isFinite(maxConcurrency)) {\n this.#queue = new Semaphore(maxConcurrency);\n }\n\n this.#trace = trace;\n }\n\n /**\n * Ensures that the Snap is ready to be used.\n *\n * @returns A promise that resolves when the Snap is ready.\n * @throws An error if the Snap could not become ready.\n */\n async ensureReady(): Promise<void> {\n return this.messenger.call('SnapAccountService:ensureReady', this.snapId);\n }\n\n /**\n * Wraps an async operation with concurrency limiting based on maxConcurrency config.\n * If maxConcurrency is Infinity (the default), the operation runs immediately without throttling.\n * Otherwise, it's queued through the semaphore to respect the concurrency limit.\n *\n * @param operation - The async operation to execute.\n * @returns The result of the operation.\n */\n protected async withMaxConcurrency<Result>(\n operation: () => Promise<Result>,\n ): Promise<Result> {\n if (this.#queue) {\n return this.#queue.runExclusive(operation);\n }\n return operation();\n }\n\n protected async trace<ReturnType>(\n request: TraceRequest,\n fn: () => Promise<ReturnType>,\n ): Promise<ReturnType> {\n return this.#trace(request, fn);\n }\n\n async #getRestrictedSnapKeyring(): Promise<RestrictedSnapKeyring> {\n // NOTE: We're not supposed to make the keyring instance escape `withKeyringV2` but\n // we have to use the `SnapKeyringV2` instance to be able to create Solana account\n // without triggering UI confirmation.\n // Also, creating account that way won't invalidate the Snap keyring state. The\n // account will get created and persisted properly with the Snap account creation\n // flow \"asynchronously\" (with `notify:accountCreated`).\n const { createAccount, createAccounts } = await this.#withSnapKeyring<{\n createAccount: SnapKeyringV2['createAccount'];\n createAccounts: SnapKeyringV2['createAccounts'];\n }>(async ({ keyring }) => ({\n createAccount: keyring.createAccount.bind(keyring),\n createAccounts: keyring.createAccounts.bind(keyring),\n }));\n\n return {\n createAccount: async (options) =>\n // We use the \"unguarded\" account creation here (see explanation above).\n await createAccount(options, {\n displayAccountNameSuggestion: false,\n displayConfirmation: false,\n setSelectedAccount: false,\n }),\n createAccounts: async (options) => await createAccounts(options),\n deleteAccount: async (id: string) =>\n // Though, when removing account, we can use the normal flow.\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.deleteAccount(id);\n }),\n };\n }\n\n #getKeyringClientFromSnapId(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest): Promise<Json> => {\n const response = await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n },\n );\n return response as Json;\n },\n });\n }\n\n async resyncAccounts(\n accounts: Bip44Account<InternalAccount>[],\n ): Promise<void> {\n await this.withSnap(async ({ keyring }) => {\n const localSnapAccounts = accounts.filter(\n (account) => account.metadata.snap?.id === this.snapId,\n );\n const snapAccounts = new Set(\n (await this.#client.listAccounts()).map((account) => account.id),\n );\n\n // NOTE: This should never happen, but if it does, we recover by deleting the\n // extra accounts from the Snap to bring it back in sync with MetaMask.\n if (localSnapAccounts.length < snapAccounts.size) {\n const autoRemoveExtraSnapAccounts =\n this.config.resyncAccounts?.autoRemoveExtraSnapAccounts ?? true;\n\n if (autoRemoveExtraSnapAccounts) {\n // Build a set of local account IDs for quick lookup\n const localAccountIds = new Set(\n localSnapAccounts.map((account) => account.id),\n );\n\n // Find and delete accounts that exist in Snap but not in MetaMask\n await Promise.all(\n [...snapAccounts].map(async (snapAccountId) => {\n try {\n if (!localAccountIds.has(snapAccountId)) {\n // This account exists in the Snap but not in MetaMask, delete it from\n // the Snap.\n await this.#client.deleteAccount(snapAccountId);\n // Update the local Set so subsequent checks use the correct size\n snapAccounts.delete(snapAccountId);\n }\n } catch (error) {\n reportError(\n this.messenger,\n `Unable to delete de-synced Snap account: ${this.snapId}`,\n error,\n {\n provider: this.getName(),\n snapAccountId,\n },\n );\n }\n }),\n );\n } else {\n const message = `Snap \"${this.snapId}\" has de-synced accounts, Snap has more accounts than MetaMask! (${localSnapAccounts.length} < ${snapAccounts.size})`;\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n return;\n }\n }\n\n // We want this part to be fast, so we only check for sizes, but we might need\n // to make a real \"diff\" between the 2 states to not miss any de-sync.\n if (localSnapAccounts.length > snapAccounts.size) {\n // We always use the MetaMask list as the main reference here.\n await Promise.all(\n localSnapAccounts.map(async (account) => {\n const { id: entropySource, groupIndex } = account.options.entropy;\n\n try {\n if (!snapAccounts.has(account.id)) {\n // We still need to remove the accounts from the Snap keyring since we're\n // about to create the same account again, which will use a new ID, but will\n // keep using the same address, and the Snap keyring does not allow this.\n await keyring.deleteAccount(account.id);\n // The Snap has no account in its state for this one, we re-create it.\n await this.createAccounts({\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n }\n } catch (error) {\n reportError(this.messenger, 'Unable to re-sync accounts', error, {\n provider: this.getName(),\n groupIndex,\n });\n }\n }),\n );\n }\n });\n }\n\n async #withSnapKeyring<CallbackResult = void>(\n operation: ({\n keyring,\n metadata,\n }: {\n keyring: SnapKeyringV2;\n metadata: KeyringMetadata;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n return this.withKeyringV2<SnapKeyringV2, CallbackResult>(\n {\n filter: (keyring) =>\n isSnapKeyring(keyring) && keyring.snapId === this.snapId,\n },\n (args) => operation(args),\n );\n }\n\n protected async withSnap<CallbackResult = void>(\n operation: (snap: {\n client: KeyringClient;\n keyring: RestrictedSnapKeyring;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n await this.ensureReady();\n\n return await operation({\n client: this.#client,\n keyring: await this.#getRestrictedSnapKeyring(),\n });\n }\n\n abstract isAccountCompatible(account: Bip44Account<InternalAccount>): boolean;\n\n protected abstract createAccountV1(\n keyring: RestrictedSnapKeyring,\n options: { entropySource: EntropySourceId; groupIndex: number },\n ): Promise<KeyringAccount>;\n\n protected toBip44Account(\n account: KeyringAccount,\n _options: { entropySource: EntropySourceId; groupIndex: number },\n ): Bip44Account<KeyringAccount> {\n assertIsBip44Account(account);\n return account;\n }\n\n protected async createBip44Accounts(\n keyring: RestrictedSnapKeyring,\n options:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withMaxConcurrency(async () => {\n let groupIndexOffset = 0;\n let snapAccounts: KeyringAccount[] = [];\n\n const batched = this.config.createAccounts.batched ?? false;\n const { entropySource } = options;\n\n const createAccountV1 = async (\n groupIndex: number,\n ): Promise<KeyringAccount> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccountV1,\n data: {\n provider: this.getName(),\n groupIndex,\n },\n },\n () =>\n this.createAccountV1(keyring, { entropySource, groupIndex }),\n ),\n this.config.createAccounts.timeoutMs,\n );\n const createAccountsV2 = async (\n optionsV2:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<KeyringAccount[]> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccounts,\n data: {\n provider: this.getName(),\n ...toCreateAccountsV2DataTraces(optionsV2),\n },\n },\n () => keyring.createAccounts(optionsV2),\n ),\n this.config.createAccounts.timeoutMs,\n );\n\n if (options.type === `${AccountCreationType.Bip44DeriveIndexRange}`) {\n if (batched) {\n // Batch account creations.\n snapAccounts = await createAccountsV2(options);\n } else {\n const { range } = options;\n\n // Create accounts one by one.\n for (\n let groupIndex = range.from;\n groupIndex <= range.to;\n groupIndex++\n ) {\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts.push(snapAccount);\n }\n }\n\n // Group indices are sequential, so we just need the starting index.\n groupIndexOffset = options.range.from;\n } else {\n if (batched) {\n // Create account using new v2-like flow (no async flow + no Snap keyring events).\n snapAccounts = await createAccountsV2(options);\n } else {\n const { groupIndex } = options;\n\n // Create account using the existing v1 flow.\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts = [snapAccount];\n }\n\n // For single account, there will only be 1 account, so we can use the\n // provided group index directly.\n groupIndexOffset = options.groupIndex;\n }\n\n return snapAccounts.map((snapAccount, index) => {\n const groupIndex = groupIndexOffset + index;\n const account = this.toBip44Account(snapAccount, {\n entropySource,\n groupIndex,\n });\n\n this.accounts.add(snapAccount.id);\n return account;\n });\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n `${AccountCreationType.Bip44DeriveIndexRange}`,\n ]);\n\n return this.withSnap(async ({ keyring }) =>\n this.createBip44Accounts(keyring, options),\n );\n }\n\n /**\n * Delete a snap account by id.\n *\n * Resolves the account's address from the tracked account, then forwards to\n * the legacy `SnapKeyring.removeAccount(address)`. The Snap keyring takes\n * care of notifying the snap to clean up its own state through the normal\n * account-removal flow (same path used by `resyncAccounts`).\n *\n * @param id - The id of the account to delete.\n */\n async deleteAccount(id: Bip44Account<KeyringAccount>['id']): Promise<void> {\n const account = this.getAccount(id);\n\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.deleteAccount(account.id);\n });\n\n this.accounts.delete(id);\n }\n\n abstract discoverAccounts(options: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]>;\n}\n\nexport const isSnapAccountProvider = (\n provider: unknown,\n): provider is SnapAccountProvider => {\n return provider instanceof SnapAccountProvider;\n};\n"]}
1
+ {"version":3,"file":"SnapAccountProvider.mjs","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertIsBip44Account } from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { TraceCallback, TraceRequest } from '@metamask/controller-utils';\nimport type { SnapKeyringV1 } from '@metamask/eth-snap-keyring';\nimport type { SnapKeyring as SnapKeyringV2 } from '@metamask/eth-snap-keyring/v2';\nimport {\n EMPTY_CAPABILITIES,\n isSnapKeyring,\n} from '@metamask/eth-snap-keyring/v2';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n} from '@metamask/keyring-api';\nimport type {\n CreateAccountBip44DeriveIndexOptions,\n CreateAccountBip44DeriveIndexRangeOptions,\n CreateAccountBip44DiscoverOptions,\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n} from '@metamask/keyring-api';\nimport type { KeyringCapabilities } from '@metamask/keyring-api/v2';\nimport type { KeyringMetadata } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type { CaipChainId } from '@metamask/utils';\nimport { Semaphore } from 'async-mutex';\n\nimport {\n toCreateAccountsV2DataTraces,\n traceFallback,\n TraceName,\n} from '../analytics';\nimport { reportError } from '../errors';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\nimport { BaseBip44AccountProvider } from './BaseBip44AccountProvider';\nimport { createSnapKeyringClient } from './SnapKeyringClient';\nimport type { Sender, SnapKeyringClient } from './SnapKeyringClient';\nimport { withRetry, withTimeout } from './utils';\n\nexport type RestrictedSnapKeyring = {\n /**\n * V1 interface, present only when the Snap does not declare v2 capabilities.\n * `undefined` for v2-only Snaps.\n *\n * Use this to make v1 calls explicit:\n * if (!keyring.v1) { throw new Error('Snap is v2-only'); }\n * keyring.v1.createAccount(options);\n */\n v1?: { createAccount: SnapKeyringV1['createAccount'] };\n createAccounts: SnapKeyringV2['createAccounts'];\n deleteAccount: SnapKeyringV2['deleteAccount'];\n};\n\nexport type SnapAccountProviderConfig = {\n maxConcurrency?: number;\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n createAccounts: {\n /**\n * Timeout for account creation operations.\n *\n * NOTE: Batching (and thus whether a single call may create multiple\n * accounts) is driven by the Snap's declared capabilities, not this config.\n * The value might have to be adapted when the Snap supports batching.\n */\n timeoutMs: number;\n };\n resyncAccounts?: {\n /**\n * Whether to automatically remove extra Snap accounts when the Snap has\n * more accounts than MetaMask. If `false`, a warning is logged instead.\n * Defaults to `true`.\n */\n autoRemoveExtraSnapAccounts?: boolean;\n };\n};\n\nexport abstract class SnapAccountProvider extends BaseBip44AccountProvider {\n readonly snapId: SnapId;\n\n protected readonly config: SnapAccountProviderConfig;\n\n /**\n * The Snap's keyring capabilities, sourced from `SnapAccountService` (which\n * reads them from the Snap's manifest). Populated the first time the client\n * is resolved; defaults to an empty capability set until then.\n */\n capabilities: KeyringCapabilities = EMPTY_CAPABILITIES;\n\n /**\n * Version-agnostic keyring client, resolved lazily once the Snap is ready and\n * its capabilities are known — see {@link SnapAccountProvider.withSnap}.\n */\n #client?: SnapKeyringClient;\n\n readonly #sender: Sender;\n\n readonly #queue?: Semaphore;\n\n readonly #trace: TraceCallback;\n\n /**\n * Scopes passed to the v1 `discoverAccounts` client method. Only used on the\n * v1 discovery path.\n *\n * TODO: Remove once all Snaps are fully v2 — discovery is then driven by the\n * Snap's own supported scopes via `createAccounts({ bip44:discover })`.\n */\n protected abstract readonly v1DiscoveryScopes: CaipChainId[];\n\n constructor(\n snapId: SnapId,\n messenger: MultichainAccountServiceMessenger,\n config: SnapAccountProviderConfig,\n /* istanbul ignore next */\n trace: TraceCallback = traceFallback,\n ) {\n super(messenger);\n\n this.snapId = snapId;\n this.#sender = this.#createSender(snapId);\n\n const maxConcurrency = config.maxConcurrency ?? Infinity;\n this.config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n maxConcurrency,\n };\n\n // Create semaphore only if concurrency is limited\n if (isFinite(maxConcurrency)) {\n this.#queue = new Semaphore(maxConcurrency);\n }\n\n this.#trace = trace;\n }\n\n /**\n * Ensures that the Snap is ready to be used.\n *\n * @returns A promise that resolves when the Snap is ready.\n * @throws An error if the Snap could not become ready.\n */\n async ensureReady(): Promise<void> {\n return this.messenger.call('SnapAccountService:ensureReady', this.snapId);\n }\n\n /**\n * Wraps an async operation with concurrency limiting based on maxConcurrency config.\n * If maxConcurrency is Infinity (the default), the operation runs immediately without throttling.\n * Otherwise, it's queued through the semaphore to respect the concurrency limit.\n *\n * @param operation - The async operation to execute.\n * @returns The result of the operation.\n */\n protected async withMaxConcurrency<Result>(\n operation: () => Promise<Result>,\n ): Promise<Result> {\n if (this.#queue) {\n return this.#queue.runExclusive(operation);\n }\n return operation();\n }\n\n protected async trace<ReturnType>(\n request: TraceRequest,\n fn: () => Promise<ReturnType>,\n ): Promise<ReturnType> {\n return this.#trace(request, fn);\n }\n\n async #getRestrictedSnapKeyring(): Promise<RestrictedSnapKeyring> {\n // NOTE: We're not supposed to make the keyring instance escape `withKeyringV2` but\n // we have to use the `SnapKeyringV2` instance to be able to create Solana account\n // without triggering UI confirmation.\n // Also, creating account that way won't invalidate the Snap keyring state. The\n // account will get created and persisted properly with the Snap account creation\n // flow \"asynchronously\" (with `notify:accountCreated`).\n const createAccount = await this.#withSnapKeyring(async ({ keyring }) => {\n if (keyring.v1) {\n return keyring.v1.createAccount.bind(keyring.v1);\n }\n\n // This method does not exist in v2.\n return undefined;\n });\n\n return {\n // V1 interface is only present for v1 Snaps, otherwise it's `undefined`.\n v1: createAccount ? { createAccount } : undefined,\n // Every v2 operations must be done through the `#withSnapKeyring` transaction:\n createAccounts: async (options) =>\n await this.#withSnapKeyring(\n async ({ keyring }) => await keyring.createAccounts(options),\n ),\n deleteAccount: async (id: string) =>\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.deleteAccount(id);\n }),\n };\n }\n\n #createSender(snapId: string): Sender {\n return {\n send: async (request: JsonRpcRequest): Promise<Json> => {\n const response = await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n },\n );\n return response as Json;\n },\n };\n }\n\n /**\n * Whether the Snap supports the v2 keyring protocol, inferred from its\n * declared capabilities (a v2-capable Snap declares BIP-44 capabilities).\n *\n * @returns `true` if the Snap is v2-capable.\n */\n protected isV2(): boolean {\n return Boolean(this.capabilities.bip44);\n }\n\n /**\n * Resolves the version-agnostic keyring client, fetching the Snap's\n * capabilities from `SnapAccountService` on first use and caching both the\n * capabilities and the resulting client.\n *\n * Callers must ensure the Snap is ready (via\n * {@link SnapAccountProvider.ensureReady}) beforehand so that the\n * capabilities are reliably populated — {@link SnapAccountProvider.withSnap}\n * guarantees this ordering.\n *\n * @returns The resolved {@link SnapKeyringClient}.\n */\n async #resolveClient(): Promise<SnapKeyringClient> {\n if (!this.#client) {\n this.capabilities = await this.messenger.call(\n 'SnapAccountService:getCapabilities',\n this.snapId,\n );\n this.#client = createSnapKeyringClient(this.#sender, this.isV2());\n }\n return this.#client;\n }\n\n async resyncAccounts(\n accounts: Bip44Account<InternalAccount>[],\n ): Promise<void> {\n await this.withSnap(async ({ client, keyring }) => {\n const localSnapAccounts = accounts.filter(\n (account) => account.metadata.snap?.id === this.snapId,\n );\n const snapAccounts = new Set(\n (await client.getAccounts()).map((account) => account.id),\n );\n\n // NOTE: This should never happen, but if it does, we recover by deleting the\n // extra accounts from the Snap to bring it back in sync with MetaMask.\n if (localSnapAccounts.length < snapAccounts.size) {\n const autoRemoveExtraSnapAccounts =\n this.config.resyncAccounts?.autoRemoveExtraSnapAccounts ?? true;\n\n if (autoRemoveExtraSnapAccounts) {\n // Build a set of local account IDs for quick lookup\n const localAccountIds = new Set(\n localSnapAccounts.map((account) => account.id),\n );\n\n // Find and delete accounts that exist in Snap but not in MetaMask\n await Promise.all(\n [...snapAccounts].map(async (snapAccountId) => {\n try {\n if (!localAccountIds.has(snapAccountId)) {\n // This account exists in the Snap but not in MetaMask, delete it from\n // the Snap.\n await client.deleteAccount(snapAccountId);\n // Update the local Set so subsequent checks use the correct size\n snapAccounts.delete(snapAccountId);\n }\n } catch (error) {\n reportError(\n this.messenger,\n `Unable to delete de-synced Snap account: ${this.snapId}`,\n error,\n {\n provider: this.getName(),\n snapAccountId,\n },\n );\n }\n }),\n );\n } else {\n const message = `Snap \"${this.snapId}\" has de-synced accounts, Snap has more accounts than MetaMask! (${localSnapAccounts.length} < ${snapAccounts.size})`;\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n return;\n }\n }\n\n // We want this part to be fast, so we only check for sizes, but we might need\n // to make a real \"diff\" between the 2 states to not miss any de-sync.\n if (localSnapAccounts.length > snapAccounts.size) {\n // We always use the MetaMask list as the main reference here.\n await Promise.all(\n localSnapAccounts.map(async (account) => {\n const { id: entropySource, groupIndex } = account.options.entropy;\n\n try {\n if (!snapAccounts.has(account.id)) {\n // We still need to remove the accounts from the Snap keyring since we're\n // about to create the same account again, which will use a new ID, but will\n // keep using the same address, and the Snap keyring does not allow this.\n await keyring.deleteAccount(account.id);\n // The Snap has no account in its state for this one, we re-create it.\n await this.createAccounts({\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n }\n } catch (error) {\n reportError(this.messenger, 'Unable to re-sync accounts', error, {\n provider: this.getName(),\n groupIndex,\n });\n }\n }),\n );\n }\n });\n }\n\n async #withSnapKeyring<CallbackResult = void>(\n operation: ({\n keyring,\n metadata,\n }: {\n keyring: SnapKeyringV2;\n metadata: KeyringMetadata;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n return this.withKeyringV2<SnapKeyringV2, CallbackResult>(\n {\n filter: (keyring) =>\n isSnapKeyring(keyring) && keyring.snapId === this.snapId,\n },\n (args) => operation(args),\n );\n }\n\n protected async withSnap<CallbackResult = void>(\n operation: (snap: {\n client: SnapKeyringClient;\n keyring: RestrictedSnapKeyring;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n await this.ensureReady();\n const client = await this.#resolveClient();\n\n return await operation({\n client,\n keyring: await this.#getRestrictedSnapKeyring(),\n });\n }\n\n abstract isAccountCompatible(account: Bip44Account<InternalAccount>): boolean;\n\n protected abstract createAccountV1(\n keyring: RestrictedSnapKeyring,\n options: { entropySource: EntropySourceId; groupIndex: number },\n ): Promise<KeyringAccount>;\n\n protected toBip44Account(\n account: KeyringAccount,\n _options: { entropySource: EntropySourceId; groupIndex: number },\n ): Bip44Account<KeyringAccount> {\n assertIsBip44Account(account);\n return account;\n }\n\n protected async createBip44Accounts(\n keyring: RestrictedSnapKeyring,\n options:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions\n | CreateAccountBip44DiscoverOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withMaxConcurrency(async () => {\n let groupIndexOffset = 0;\n let snapAccounts: KeyringAccount[] = [];\n\n // v2 Snaps expose `createAccounts` but no singular `createAccount`, so\n // they must always go through the batched flow. v1 Snaps only have the\n // singular `createAccount`.\n const batched = this.isV2();\n const { entropySource } = options;\n\n const createAccountV1 = async (\n groupIndex: number,\n ): Promise<KeyringAccount> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccountV1,\n data: {\n provider: this.getName(),\n groupIndex,\n },\n },\n () =>\n this.createAccountV1(keyring, { entropySource, groupIndex }),\n ),\n this.config.createAccounts.timeoutMs,\n );\n const createAccountsV2 = async (\n optionsV2:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions\n | CreateAccountBip44DiscoverOptions,\n ): Promise<KeyringAccount[]> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccounts,\n data: {\n provider: this.getName(),\n ...toCreateAccountsV2DataTraces(optionsV2),\n },\n },\n () => keyring.createAccounts(optionsV2),\n ),\n this.config.createAccounts.timeoutMs,\n );\n\n if (options.type === `${AccountCreationType.Bip44DeriveIndexRange}`) {\n if (batched) {\n // Batch account creations.\n snapAccounts = await createAccountsV2(options);\n } else {\n const { range } = options;\n\n // Create accounts one by one.\n for (\n let groupIndex = range.from;\n groupIndex <= range.to;\n groupIndex++\n ) {\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts.push(snapAccount);\n }\n }\n\n // Group indices are sequential, so we just need the starting index.\n groupIndexOffset = options.range.from;\n } else {\n if (batched) {\n // Create account using new v2-like flow (no async flow + no Snap keyring events).\n snapAccounts = await createAccountsV2(options);\n } else {\n const { groupIndex } = options;\n\n // Create account using the existing v1 flow.\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts = [snapAccount];\n }\n\n // For single account, there will only be 1 account, so we can use the\n // provided group index directly.\n groupIndexOffset = options.groupIndex;\n }\n\n return snapAccounts.map((snapAccount, index) => {\n const groupIndex = groupIndexOffset + index;\n const account = this.toBip44Account(snapAccount, {\n entropySource,\n groupIndex,\n });\n\n this.accounts.add(snapAccount.id);\n return account;\n });\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n `${AccountCreationType.Bip44DeriveIndexRange}`,\n ]);\n\n return this.withSnap(async ({ keyring }) =>\n this.createBip44Accounts(keyring, options),\n );\n }\n\n /**\n * Delete a snap account by id.\n *\n * Resolves the account's address from the tracked account, then forwards to\n * the legacy `SnapKeyring.removeAccount(address)`. The Snap keyring takes\n * care of notifying the snap to clean up its own state through the normal\n * account-removal flow (same path used by `resyncAccounts`).\n *\n * @param id - The id of the account to delete.\n */\n async deleteAccount(id: Bip44Account<KeyringAccount>['id']): Promise<void> {\n const account = this.getAccount(id);\n\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.deleteAccount(account.id);\n });\n\n this.accounts.delete(id);\n }\n\n /**\n * Discovers accounts for the given entropy source and group index.\n *\n * v2 Snaps drive discovery through `createAccounts({ bip44:discover })`: the\n * Snap checks for on-chain activity (using its own supported scopes) and\n * returns the created account(s), or nothing once discovery is exhausted.\n *\n * v1 Snaps use the client's `discoverAccounts` to detect activity on\n * {@link v1DiscoveryScopes}, then create the account for the group index.\n *\n * @param options - The discovery options.\n * @param options.entropySource - The entropy source to discover accounts for.\n * @param options.groupIndex - The group index to discover accounts for.\n * @returns The discovered (and created) accounts, or an empty array when\n * there is nothing to discover at this group index.\n */\n async discoverAccounts({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withSnap(async ({ client, keyring }) =>\n this.trace(\n {\n name: TraceName.SnapDiscoverAccounts,\n data: {\n provider: this.getName(),\n },\n },\n async () => {\n if (!this.config.discovery.enabled) {\n return [];\n }\n\n if (this.isV2()) {\n // The v2 client has no `discoverAccounts`, so discovery is only\n // possible when the Snap supports `bip44:discover`. Otherwise there\n // is no way to discover and we report nothing.\n if (!this.capabilities.bip44?.discover) {\n return [];\n }\n\n // v2: the Snap detects on-chain activity and creates the account in\n // a single `createAccounts({ bip44:discover })` call. An empty\n // result means discovery is exhausted at this group index.\n return this.createBip44Accounts(keyring, {\n type: AccountCreationType.Bip44Discover,\n entropySource,\n groupIndex,\n });\n }\n\n // v1: detect activity via the client, then create the account for\n // this group index.\n const discoveredAccounts = await withRetry(\n () =>\n withTimeout(\n () =>\n client.discoverAccounts(\n this.v1DiscoveryScopes,\n entropySource,\n groupIndex,\n ),\n this.config.discovery.timeoutMs,\n ),\n {\n maxAttempts: this.config.discovery.maxAttempts,\n backOffMs: this.config.discovery.backOffMs,\n },\n );\n\n if (!discoveredAccounts.length) {\n return [];\n }\n\n return this.createBip44Accounts(keyring, {\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n },\n ),\n );\n }\n}\n\nexport const isSnapAccountProvider = (\n provider: unknown,\n): provider is SnapAccountProvider => {\n return provider instanceof SnapAccountProvider;\n};\n"]}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSnapKeyringClient = void 0;
4
+ const keyring_snap_client_1 = require("@metamask/keyring-snap-client");
5
+ const v2_1 = require("@metamask/keyring-snap-client/v2");
6
+ /**
7
+ * Builds a version-agnostic {@link SnapKeyringClient} backed by either the v1
8
+ * or v2 keyring client, based on the Snap's declared capabilities.
9
+ *
10
+ * @param sender - The transport used to talk to the Snap.
11
+ * @param isV2 - Whether to back the client with the v2 keyring client.
12
+ * @returns A {@link SnapKeyringClient}.
13
+ */
14
+ function createSnapKeyringClient(sender, isV2) {
15
+ if (isV2) {
16
+ const client = new v2_1.KeyringClient(sender);
17
+ return {
18
+ getAccounts: async () => client.getAccounts(),
19
+ deleteAccount: async (id) => client.deleteAccount(id),
20
+ discoverAccounts: async () => {
21
+ // v2 discovery is driven by `createAccounts({ bip44:discover })` through
22
+ // the bridge keyring, so the client is never used for discovery here.
23
+ throw new Error('discoverAccounts is not supported on the v2 keyring client');
24
+ },
25
+ };
26
+ }
27
+ const client = new keyring_snap_client_1.KeyringClient(sender);
28
+ return {
29
+ getAccounts: async () => client.listAccounts(),
30
+ deleteAccount: async (id) => client.deleteAccount(id),
31
+ discoverAccounts: async (scopes, entropySource, groupIndex) => client.discoverAccounts(scopes, entropySource, groupIndex),
32
+ };
33
+ }
34
+ exports.createSnapKeyringClient = createSnapKeyringClient;
35
+ //# sourceMappingURL=SnapKeyringClient.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SnapKeyringClient.cjs","sourceRoot":"","sources":["../../src/providers/SnapKeyringClient.ts"],"names":[],"mappings":";;;AACA,uEAA8D;AAC9D,yDAAoF;AAmDpF;;;;;;;GAOG;AACH,SAAgB,uBAAuB,CACrC,MAAc,EACd,IAAa;IAEb,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,IAAI,kBAAe,CAAC,MAAM,CAAC,CAAC;QAC3C,OAAO;YACL,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;YAC7C,aAAa,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YACrD,gBAAgB,EAAE,KAAK,IAAkC,EAAE;gBACzD,yEAAyE;gBACzE,sEAAsE;gBACtE,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,mCAAa,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO;QACL,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE;QAC9C,aAAa,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QACrD,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,EAAE,CAC5D,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC;KAC7D,CAAC;AACJ,CAAC;AA1BD,0DA0BC","sourcesContent":["import type { EntropySourceId, KeyringAccount } from '@metamask/keyring-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport { KeyringClient as KeyringClientV2 } from '@metamask/keyring-snap-client/v2';\nimport type { CaipChainId } from '@metamask/utils';\n\n/**\n * Transport used by both the v1 and v2 keyring clients. Matches the object the\n * {@link KeyringClient} constructor expects.\n */\nexport type Sender = ConstructorParameters<typeof KeyringClient>[0];\n\ntype DiscoveredAccount = Awaited<\n ReturnType<KeyringClient['discoverAccounts']>\n>[number];\n\n/**\n * Thin abstraction over the v1 and v2 keyring RPC clients so that provider call\n * sites (account re-sync and v1 discovery) don't have to branch on the keyring\n * protocol version. The v1 and v2 clients expose different method names (e.g.\n * v1 `listAccounts` vs v2 `getAccounts`), and v2 has no `discoverAccounts` — v2\n * discovery flows through `createAccounts({ bip44:discover })` on the bridge\n * keyring instead.\n */\nexport type SnapKeyringClient = {\n /**\n * Returns the accounts the Snap currently holds.\n */\n getAccounts(): Promise<KeyringAccount[]>;\n\n /**\n * Deletes an account by id from the Snap.\n *\n * @param id - The id of the account to delete.\n */\n deleteAccount(id: string): Promise<void>;\n\n /**\n * Discovers accounts for the given entropy source and group index.\n *\n * Only supported on the v1 client; the v2 client throws, since v2 discovery\n * goes through `createAccounts({ bip44:discover })`.\n *\n * @param scopes - The scopes to discover accounts on.\n * @param entropySource - The entropy source to discover accounts for.\n * @param groupIndex - The group index to discover accounts for.\n */\n discoverAccounts(\n scopes: CaipChainId[],\n entropySource: EntropySourceId,\n groupIndex: number,\n ): Promise<DiscoveredAccount[]>;\n};\n\n/**\n * Builds a version-agnostic {@link SnapKeyringClient} backed by either the v1\n * or v2 keyring client, based on the Snap's declared capabilities.\n *\n * @param sender - The transport used to talk to the Snap.\n * @param isV2 - Whether to back the client with the v2 keyring client.\n * @returns A {@link SnapKeyringClient}.\n */\nexport function createSnapKeyringClient(\n sender: Sender,\n isV2: boolean,\n): SnapKeyringClient {\n if (isV2) {\n const client = new KeyringClientV2(sender);\n return {\n getAccounts: async () => client.getAccounts(),\n deleteAccount: async (id) => client.deleteAccount(id),\n discoverAccounts: async (): Promise<DiscoveredAccount[]> => {\n // v2 discovery is driven by `createAccounts({ bip44:discover })` through\n // the bridge keyring, so the client is never used for discovery here.\n throw new Error(\n 'discoverAccounts is not supported on the v2 keyring client',\n );\n },\n };\n }\n\n const client = new KeyringClient(sender);\n return {\n getAccounts: async () => client.listAccounts(),\n deleteAccount: async (id) => client.deleteAccount(id),\n discoverAccounts: async (scopes, entropySource, groupIndex) =>\n client.discoverAccounts(scopes, entropySource, groupIndex),\n };\n}\n"]}
@@ -0,0 +1,51 @@
1
+ import type { EntropySourceId, KeyringAccount } from "@metamask/keyring-api";
2
+ import { KeyringClient } from "@metamask/keyring-snap-client";
3
+ import type { CaipChainId } from "@metamask/utils";
4
+ /**
5
+ * Transport used by both the v1 and v2 keyring clients. Matches the object the
6
+ * {@link KeyringClient} constructor expects.
7
+ */
8
+ export type Sender = ConstructorParameters<typeof KeyringClient>[0];
9
+ type DiscoveredAccount = Awaited<ReturnType<KeyringClient['discoverAccounts']>>[number];
10
+ /**
11
+ * Thin abstraction over the v1 and v2 keyring RPC clients so that provider call
12
+ * sites (account re-sync and v1 discovery) don't have to branch on the keyring
13
+ * protocol version. The v1 and v2 clients expose different method names (e.g.
14
+ * v1 `listAccounts` vs v2 `getAccounts`), and v2 has no `discoverAccounts` — v2
15
+ * discovery flows through `createAccounts({ bip44:discover })` on the bridge
16
+ * keyring instead.
17
+ */
18
+ export type SnapKeyringClient = {
19
+ /**
20
+ * Returns the accounts the Snap currently holds.
21
+ */
22
+ getAccounts(): Promise<KeyringAccount[]>;
23
+ /**
24
+ * Deletes an account by id from the Snap.
25
+ *
26
+ * @param id - The id of the account to delete.
27
+ */
28
+ deleteAccount(id: string): Promise<void>;
29
+ /**
30
+ * Discovers accounts for the given entropy source and group index.
31
+ *
32
+ * Only supported on the v1 client; the v2 client throws, since v2 discovery
33
+ * goes through `createAccounts({ bip44:discover })`.
34
+ *
35
+ * @param scopes - The scopes to discover accounts on.
36
+ * @param entropySource - The entropy source to discover accounts for.
37
+ * @param groupIndex - The group index to discover accounts for.
38
+ */
39
+ discoverAccounts(scopes: CaipChainId[], entropySource: EntropySourceId, groupIndex: number): Promise<DiscoveredAccount[]>;
40
+ };
41
+ /**
42
+ * Builds a version-agnostic {@link SnapKeyringClient} backed by either the v1
43
+ * or v2 keyring client, based on the Snap's declared capabilities.
44
+ *
45
+ * @param sender - The transport used to talk to the Snap.
46
+ * @param isV2 - Whether to back the client with the v2 keyring client.
47
+ * @returns A {@link SnapKeyringClient}.
48
+ */
49
+ export declare function createSnapKeyringClient(sender: Sender, isV2: boolean): SnapKeyringClient;
50
+ export {};
51
+ //# sourceMappingURL=SnapKeyringClient.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SnapKeyringClient.d.cts","sourceRoot":"","sources":["../../src/providers/SnapKeyringClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,8BAA8B;AAC7E,OAAO,EAAE,aAAa,EAAE,sCAAsC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,wBAAwB;AAEnD;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,qBAAqB,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpE,KAAK,iBAAiB,GAAG,OAAO,CAC9B,UAAU,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAC9C,CAAC,MAAM,CAAC,CAAC;AAEV;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAEzC;;;;OAIG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC;;;;;;;;;OASG;IACH,gBAAgB,CACd,MAAM,EAAE,WAAW,EAAE,EACrB,aAAa,EAAE,eAAe,EAC9B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;CACjC,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,iBAAiB,CAuBnB"}