@metamask-previews/multichain-account-service 0.3.0-preview-5e0fb2b → 0.3.0-preview-8755e953

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 (86) hide show
  1. package/CHANGELOG.md +1 -6
  2. package/dist/MultichainAccountGroup.cjs.map +1 -1
  3. package/dist/MultichainAccountGroup.d.cts +3 -3
  4. package/dist/MultichainAccountGroup.d.cts.map +1 -1
  5. package/dist/MultichainAccountGroup.d.mts +3 -3
  6. package/dist/MultichainAccountGroup.d.mts.map +1 -1
  7. package/dist/MultichainAccountGroup.mjs.map +1 -1
  8. package/dist/MultichainAccountService.cjs +1 -16
  9. package/dist/MultichainAccountService.cjs.map +1 -1
  10. package/dist/MultichainAccountService.d.cts +8 -21
  11. package/dist/MultichainAccountService.d.cts.map +1 -1
  12. package/dist/MultichainAccountService.d.mts +8 -21
  13. package/dist/MultichainAccountService.d.mts.map +1 -1
  14. package/dist/MultichainAccountService.mjs +1 -16
  15. package/dist/MultichainAccountService.mjs.map +1 -1
  16. package/dist/MultichainAccountWallet.cjs +13 -115
  17. package/dist/MultichainAccountWallet.cjs.map +1 -1
  18. package/dist/MultichainAccountWallet.d.cts +1 -22
  19. package/dist/MultichainAccountWallet.d.cts.map +1 -1
  20. package/dist/MultichainAccountWallet.d.mts +1 -22
  21. package/dist/MultichainAccountWallet.d.mts.map +1 -1
  22. package/dist/MultichainAccountWallet.mjs +13 -115
  23. package/dist/MultichainAccountWallet.mjs.map +1 -1
  24. package/dist/index.cjs +1 -5
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +0 -1
  27. package/dist/index.d.cts.map +1 -1
  28. package/dist/index.d.mts +0 -1
  29. package/dist/index.d.mts.map +1 -1
  30. package/dist/index.mjs +0 -1
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/providers/BaseAccountProvider.cjs +1 -30
  33. package/dist/providers/BaseAccountProvider.cjs.map +1 -1
  34. package/dist/providers/BaseAccountProvider.d.cts +5 -32
  35. package/dist/providers/BaseAccountProvider.d.cts.map +1 -1
  36. package/dist/providers/BaseAccountProvider.d.mts +5 -32
  37. package/dist/providers/BaseAccountProvider.d.mts.map +1 -1
  38. package/dist/providers/BaseAccountProvider.mjs +0 -27
  39. package/dist/providers/BaseAccountProvider.mjs.map +1 -1
  40. package/dist/providers/EvmAccountProvider.cjs +0 -35
  41. package/dist/providers/EvmAccountProvider.cjs.map +1 -1
  42. package/dist/providers/EvmAccountProvider.d.cts +0 -66
  43. package/dist/providers/EvmAccountProvider.d.cts.map +1 -1
  44. package/dist/providers/EvmAccountProvider.d.mts +0 -66
  45. package/dist/providers/EvmAccountProvider.d.mts.map +1 -1
  46. package/dist/providers/EvmAccountProvider.mjs +1 -36
  47. package/dist/providers/EvmAccountProvider.mjs.map +1 -1
  48. package/dist/providers/SolAccountProvider.cjs +1 -31
  49. package/dist/providers/SolAccountProvider.cjs.map +1 -1
  50. package/dist/providers/SolAccountProvider.d.cts +3 -14
  51. package/dist/providers/SolAccountProvider.d.cts.map +1 -1
  52. package/dist/providers/SolAccountProvider.d.mts +3 -14
  53. package/dist/providers/SolAccountProvider.d.mts.map +1 -1
  54. package/dist/providers/SolAccountProvider.mjs +3 -33
  55. package/dist/providers/SolAccountProvider.mjs.map +1 -1
  56. package/dist/tests/accounts.cjs +0 -9
  57. package/dist/tests/accounts.cjs.map +1 -1
  58. package/dist/tests/accounts.d.cts +55 -27
  59. package/dist/tests/accounts.d.cts.map +1 -1
  60. package/dist/tests/accounts.d.mts +55 -27
  61. package/dist/tests/accounts.d.mts.map +1 -1
  62. package/dist/tests/accounts.mjs +0 -9
  63. package/dist/tests/accounts.mjs.map +1 -1
  64. package/dist/types.cjs.map +1 -1
  65. package/dist/types.d.cts +1 -5
  66. package/dist/types.d.cts.map +1 -1
  67. package/dist/types.d.mts +1 -5
  68. package/dist/types.d.mts.map +1 -1
  69. package/dist/types.mjs.map +1 -1
  70. package/package.json +4 -6
  71. package/dist/providers/SnapAccountProvider.cjs +0 -29
  72. package/dist/providers/SnapAccountProvider.cjs.map +0 -1
  73. package/dist/providers/SnapAccountProvider.d.cts +0 -22
  74. package/dist/providers/SnapAccountProvider.d.cts.map +0 -1
  75. package/dist/providers/SnapAccountProvider.d.mts +0 -22
  76. package/dist/providers/SnapAccountProvider.d.mts.map +0 -1
  77. package/dist/providers/SnapAccountProvider.mjs +0 -25
  78. package/dist/providers/SnapAccountProvider.mjs.map +0 -1
  79. package/dist/providers/index.cjs +0 -22
  80. package/dist/providers/index.cjs.map +0 -1
  81. package/dist/providers/index.d.cts +0 -5
  82. package/dist/providers/index.d.cts.map +0 -1
  83. package/dist/providers/index.d.mts +0 -5
  84. package/dist/providers/index.d.mts.map +0 -1
  85. package/dist/providers/index.mjs +0 -6
  86. package/dist/providers/index.mjs.map +0 -1
@@ -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 _MultichainAccountWallet_id, _MultichainAccountWallet_providers, _MultichainAccountWallet_entropySource, _MultichainAccountWallet_accountGroups;
13
+ var _MultichainAccountWallet_id, _MultichainAccountWallet_providers, _MultichainAccountWallet_entropySource, _MultichainAccountWallet_accounts;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.MultichainAccountWallet = void 0;
16
16
  const account_api_1 = require("@metamask/account-api");
@@ -26,11 +26,11 @@ class MultichainAccountWallet {
26
26
  _MultichainAccountWallet_id.set(this, void 0);
27
27
  _MultichainAccountWallet_providers.set(this, void 0);
28
28
  _MultichainAccountWallet_entropySource.set(this, void 0);
29
- _MultichainAccountWallet_accountGroups.set(this, void 0);
29
+ _MultichainAccountWallet_accounts.set(this, void 0);
30
30
  __classPrivateFieldSet(this, _MultichainAccountWallet_id, (0, account_api_1.toMultichainAccountWalletId)(entropySource), "f");
31
31
  __classPrivateFieldSet(this, _MultichainAccountWallet_providers, providers, "f");
32
32
  __classPrivateFieldSet(this, _MultichainAccountWallet_entropySource, entropySource, "f");
33
- __classPrivateFieldSet(this, _MultichainAccountWallet_accountGroups, new Map(), "f");
33
+ __classPrivateFieldSet(this, _MultichainAccountWallet_accounts, new Map(), "f");
34
34
  // Initial synchronization.
35
35
  this.sync();
36
36
  }
@@ -49,32 +49,23 @@ class MultichainAccountWallet {
49
49
  continue;
50
50
  }
51
51
  // This multichain account might exists already.
52
- let multichainAccount = __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").get(entropy.groupIndex);
52
+ let multichainAccount = __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(entropy.groupIndex);
53
53
  if (!multichainAccount) {
54
54
  multichainAccount = new MultichainAccountGroup_1.MultichainAccountGroup({
55
55
  groupIndex: entropy.groupIndex,
56
56
  wallet: this,
57
57
  providers: __classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f"),
58
58
  });
59
- // This existing multichain account group might differ from the
60
- // `createMultichainAccountGroup` behavior. When creating a new
61
- // group, we expect the providers to all succeed. But here, we're
62
- // just fetching the account lists from them, so this group might
63
- // not be "aligned" yet (e.g having a missing Solana account).
64
- //
65
- // Since "aligning" is an async operation, it would have to be run
66
- // after the first-sync.
67
- // TODO: Implement align mechanism to create "missing" accounts.
68
- __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").set(entropy.groupIndex, multichainAccount);
59
+ __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").set(entropy.groupIndex, multichainAccount);
69
60
  }
70
61
  }
71
62
  }
72
63
  // Now force-sync all remaining multichain accounts.
73
- for (const [groupIndex, multichainAccount,] of __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").entries()) {
64
+ for (const [groupIndex, multichainAccount] of __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").entries()) {
74
65
  multichainAccount.sync();
75
66
  // Clean up old multichain accounts.
76
67
  if (!multichainAccount.hasAccounts()) {
77
- __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").delete(groupIndex);
68
+ __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").delete(groupIndex);
78
69
  }
79
70
  }
80
71
  }
@@ -112,15 +103,15 @@ class MultichainAccountWallet {
112
103
  getAccountGroup(id) {
113
104
  // We consider the "default case" to be mapped to index 0.
114
105
  if (id === (0, account_api_2.toDefaultAccountGroupId)(this.id)) {
115
- return __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").get(0);
106
+ return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(0);
116
107
  }
117
108
  // If it is not a valid ID, we cannot extract the group index
118
109
  // from it, so we fail fast.
119
110
  if (!(0, account_api_1.isMultichainAccountGroupId)(id)) {
120
111
  return undefined;
121
112
  }
122
- const groupIndex = (0, account_api_1.getGroupIndexFromMultichainAccountGroupId)(id);
123
- return __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").get(groupIndex);
113
+ const groupIndex = (0, account_api_1.getGroupIndexFromMultichainAccountId)(id);
114
+ return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(groupIndex);
124
115
  }
125
116
  /**
126
117
  * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.
@@ -137,7 +128,7 @@ class MultichainAccountWallet {
137
128
  * @returns The multichain account associated with the given index.
138
129
  */
139
130
  getMultichainAccountGroup(groupIndex) {
140
- return __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").get(groupIndex);
131
+ return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(groupIndex);
141
132
  }
142
133
  /**
143
134
  * Gets all multichain account groups.
@@ -145,102 +136,9 @@ class MultichainAccountWallet {
145
136
  * @returns The multichain accounts.
146
137
  */
147
138
  getMultichainAccountGroups() {
148
- return Array.from(__classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").values()); // TODO: Prevent copy here.
149
- }
150
- /**
151
- * Gets next group index for this wallet.
152
- *
153
- * @returns The next group index of this wallet.
154
- */
155
- getNextGroupIndex() {
156
- // We do not check for gaps.
157
- return (Math.max(-1, // So it will default to 0 if no groups.
158
- ...__classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").keys()) + 1);
159
- }
160
- /**
161
- * Creates a multichain account group for a given group index.
162
- *
163
- * @param groupIndex - The group index to use.
164
- * @throws If any of the account providers fails to create their accounts.
165
- * @returns The multichain account group for this group index.
166
- */
167
- async createMultichainAccountGroup(groupIndex) {
168
- const nextGroupIndex = this.getNextGroupIndex();
169
- if (groupIndex > nextGroupIndex) {
170
- throw new Error(`You cannot use a group index that is higher than the next available one: expected <=${nextGroupIndex}, got ${groupIndex}`);
171
- }
172
- let group = this.getMultichainAccountGroup(groupIndex);
173
- if (group) {
174
- // If the group already exists, we just `sync` it and returns the same
175
- // reference.
176
- group.sync();
177
- return group;
178
- }
179
- const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f").map((provider) => provider.createAccounts({
180
- entropySource: __classPrivateFieldGet(this, _MultichainAccountWallet_entropySource, "f"),
181
- groupIndex,
182
- })));
183
- // --------------------------------------------------------------------------------
184
- // READ THIS CAREFULLY:
185
- //
186
- // Since we're not "fully supporting multichain" for now, we still rely on single
187
- // :accountCreated events to sync multichain account groups and wallets. Which means
188
- // that even if of the provider fails, some accounts will still be created on some
189
- // other providers and will become "available" on the `AccountsController`, like:
190
- //
191
- // 1. Creating a multichain account group for index 1
192
- // 2. EvmAccountProvider.createAccounts returns the EVM account for index 1
193
- // * AccountsController WILL fire :accountCreated for this account
194
- // * This account WILL BE "available" on the AccountsController state
195
- // 3. SolAccountProvider.createAccounts fails to create a Solana account for index 1
196
- // * AccountsController WON't fire :accountCreated for this account
197
- // * This account WON'T be "available" on the Account
198
- // 4. MultichainAccountService will receive a :accountCreated for the EVM account from
199
- // step 2 and will create a new multichain account group for index 1, but it won't
200
- // receive any event for the Solana account of this group. Thus, this group won't be
201
- // "aligned" (missing "blockchain account" on this group).
202
- //
203
- // --------------------------------------------------------------------------------
204
- // If any of the provider failed to create their accounts, then we consider the
205
- // multichain account group to have failed too.
206
- if (results.some((result) => result.status === 'rejected')) {
207
- // NOTE: Some accounts might still have been created on other account providers. We
208
- // don't rollback them.
209
- const error = `Unable to create multichain account group for index: ${groupIndex}`;
210
- let warn = `${error}:`;
211
- for (const result of results) {
212
- if (result.status === 'rejected') {
213
- warn += `\n- ${result.reason}`;
214
- }
215
- }
216
- console.warn(warn);
217
- throw new Error(error);
218
- }
219
- // Because of the :accountAdded automatic sync, we might already have created the
220
- // group, so we first try to get it.
221
- group = this.getMultichainAccountGroup(groupIndex);
222
- if (!group) {
223
- // If for some reason it's still not created, we're creating it explicitly now:
224
- group = new MultichainAccountGroup_1.MultichainAccountGroup({
225
- wallet: this,
226
- providers: __classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f"),
227
- groupIndex,
228
- });
229
- }
230
- // Register the account to our internal map.
231
- __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").set(groupIndex, group); // `group` cannot be undefined here.
232
- return group;
233
- }
234
- /**
235
- * Creates the next multichain account group.
236
- *
237
- * @throws If any of the account providers fails to create their accounts.
238
- * @returns The multichain account group for the next group index available.
239
- */
240
- async createNextMultichainAccountGroup() {
241
- return this.createMultichainAccountGroup(this.getNextGroupIndex());
139
+ return Array.from(__classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").values()); // TODO: Prevent copy here.
242
140
  }
243
141
  }
244
142
  exports.MultichainAccountWallet = MultichainAccountWallet;
245
- _MultichainAccountWallet_id = new WeakMap(), _MultichainAccountWallet_providers = new WeakMap(), _MultichainAccountWallet_entropySource = new WeakMap(), _MultichainAccountWallet_accountGroups = new WeakMap();
143
+ _MultichainAccountWallet_id = new WeakMap(), _MultichainAccountWallet_providers = new WeakMap(), _MultichainAccountWallet_entropySource = new WeakMap(), _MultichainAccountWallet_accounts = new WeakMap();
246
144
  //# sourceMappingURL=MultichainAccountWallet.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountWallet.cjs","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getGroupIndexFromMultichainAccountGroupId,\n isMultichainAccountGroupId,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport { toDefaultAccountGroupId } from '@metamask/account-api';\nimport { AccountWalletType } from '@metamask/account-api';\nimport type {\n Bip44Account,\n MultichainAccountWalletId,\n MultichainAccountWallet as MultichainAccountWalletDefinition,\n} from '@metamask/account-api';\nimport type { AccountGroupId } from '@metamask/account-api';\nimport type { AccountProvider } from '@metamask/account-api';\nimport {\n type EntropySourceId,\n type KeyringAccount,\n} from '@metamask/keyring-api';\n\nimport { MultichainAccountGroup } from './MultichainAccountGroup';\n\n/**\n * A multichain account wallet that holds multiple multichain accounts (one multichain account per\n * group index).\n */\nexport class MultichainAccountWallet<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountWalletDefinition<Account>\n{\n readonly #id: MultichainAccountWalletId;\n\n readonly #providers: AccountProvider<Account>[];\n\n readonly #entropySource: EntropySourceId;\n\n readonly #accountGroups: Map<number, MultichainAccountGroup<Account>>;\n\n constructor({\n providers,\n entropySource,\n }: {\n providers: AccountProvider<Account>[];\n entropySource: EntropySourceId;\n }) {\n this.#id = toMultichainAccountWalletId(entropySource);\n this.#providers = providers;\n this.#entropySource = entropySource;\n this.#accountGroups = new Map();\n\n // Initial synchronization.\n this.sync();\n }\n\n /**\n * Force wallet synchronization.\n *\n * This can be used if account providers got new accounts that the wallet\n * doesn't know about.\n */\n sync(): void {\n for (const provider of this.#providers) {\n for (const account of provider.getAccounts()) {\n const { entropy } = account.options;\n\n // Filter for this wallet only.\n if (entropy.id !== this.entropySource) {\n continue;\n }\n\n // This multichain account might exists already.\n let multichainAccount = this.#accountGroups.get(entropy.groupIndex);\n if (!multichainAccount) {\n multichainAccount = new MultichainAccountGroup<Account>({\n groupIndex: entropy.groupIndex,\n wallet: this,\n providers: this.#providers,\n });\n\n // This existing multichain account group might differ from the\n // `createMultichainAccountGroup` behavior. When creating a new\n // group, we expect the providers to all succeed. But here, we're\n // just fetching the account lists from them, so this group might\n // not be \"aligned\" yet (e.g having a missing Solana account).\n //\n // Since \"aligning\" is an async operation, it would have to be run\n // after the first-sync.\n // TODO: Implement align mechanism to create \"missing\" accounts.\n\n this.#accountGroups.set(entropy.groupIndex, multichainAccount);\n }\n }\n }\n\n // Now force-sync all remaining multichain accounts.\n for (const [\n groupIndex,\n multichainAccount,\n ] of this.#accountGroups.entries()) {\n multichainAccount.sync();\n\n // Clean up old multichain accounts.\n if (!multichainAccount.hasAccounts()) {\n this.#accountGroups.delete(groupIndex);\n }\n }\n }\n\n /**\n * Gets the multichain account wallet ID.\n *\n * @returns The multichain account wallet ID.\n */\n get id(): MultichainAccountWalletId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.\n *\n * @returns The multichain account wallet type.\n */\n get type(): AccountWalletType.Entropy {\n return AccountWalletType.Entropy;\n }\n\n /**\n * Gets the multichain account wallet entropy source.\n *\n * @returns The multichain account wallet entropy source.\n */\n get entropySource(): EntropySourceId {\n return this.#entropySource;\n }\n\n /**\n * Gets multichain account for a given ID.\n * The default group ID will default to the multichain account with index 0.\n *\n * @param id - Account group ID.\n * @returns Account group.\n */\n getAccountGroup(\n id: AccountGroupId,\n ): MultichainAccountGroup<Account> | undefined {\n // We consider the \"default case\" to be mapped to index 0.\n if (id === toDefaultAccountGroupId(this.id)) {\n return this.#accountGroups.get(0);\n }\n\n // If it is not a valid ID, we cannot extract the group index\n // from it, so we fail fast.\n if (!isMultichainAccountGroupId(id)) {\n return undefined;\n }\n\n const groupIndex = getGroupIndexFromMultichainAccountGroupId(id);\n return this.#accountGroups.get(groupIndex);\n }\n\n /**\n * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.\n *\n * @returns The multichain accounts.\n */\n getAccountGroups(): MultichainAccountGroup<Account>[] {\n return this.getMultichainAccountGroups();\n }\n\n /**\n * Gets multichain account group for a given index.\n *\n * @param groupIndex - Multichain account index.\n * @returns The multichain account associated with the given index.\n */\n getMultichainAccountGroup(\n groupIndex: number,\n ): MultichainAccountGroup<Account> | undefined {\n return this.#accountGroups.get(groupIndex);\n }\n\n /**\n * Gets all multichain account groups.\n *\n * @returns The multichain accounts.\n */\n getMultichainAccountGroups(): MultichainAccountGroup<Account>[] {\n return Array.from(this.#accountGroups.values()); // TODO: Prevent copy here.\n }\n\n /**\n * Gets next group index for this wallet.\n *\n * @returns The next group index of this wallet.\n */\n getNextGroupIndex(): number {\n // We do not check for gaps.\n return (\n Math.max(\n -1, // So it will default to 0 if no groups.\n ...this.#accountGroups.keys(),\n ) + 1\n );\n }\n\n /**\n * Creates a multichain account group for a given group index.\n *\n * @param groupIndex - The group index to use.\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for this group index.\n */\n async createMultichainAccountGroup(\n groupIndex: number,\n ): Promise<MultichainAccountGroup<Account>> {\n const nextGroupIndex = this.getNextGroupIndex();\n if (groupIndex > nextGroupIndex) {\n throw new Error(\n `You cannot use a group index that is higher than the next available one: expected <=${nextGroupIndex}, got ${groupIndex}`,\n );\n }\n\n let group = this.getMultichainAccountGroup(groupIndex);\n if (group) {\n // If the group already exists, we just `sync` it and returns the same\n // reference.\n group.sync();\n\n return group;\n }\n\n const results = await Promise.allSettled(\n this.#providers.map((provider) =>\n provider.createAccounts({\n entropySource: this.#entropySource,\n groupIndex,\n }),\n ),\n );\n\n // --------------------------------------------------------------------------------\n // READ THIS CAREFULLY:\n //\n // Since we're not \"fully supporting multichain\" for now, we still rely on single\n // :accountCreated events to sync multichain account groups and wallets. Which means\n // that even if of the provider fails, some accounts will still be created on some\n // other providers and will become \"available\" on the `AccountsController`, like:\n //\n // 1. Creating a multichain account group for index 1\n // 2. EvmAccountProvider.createAccounts returns the EVM account for index 1\n // * AccountsController WILL fire :accountCreated for this account\n // * This account WILL BE \"available\" on the AccountsController state\n // 3. SolAccountProvider.createAccounts fails to create a Solana account for index 1\n // * AccountsController WON't fire :accountCreated for this account\n // * This account WON'T be \"available\" on the Account\n // 4. MultichainAccountService will receive a :accountCreated for the EVM account from\n // step 2 and will create a new multichain account group for index 1, but it won't\n // receive any event for the Solana account of this group. Thus, this group won't be\n // \"aligned\" (missing \"blockchain account\" on this group).\n //\n // --------------------------------------------------------------------------------\n\n // If any of the provider failed to create their accounts, then we consider the\n // multichain account group to have failed too.\n if (results.some((result) => result.status === 'rejected')) {\n // NOTE: Some accounts might still have been created on other account providers. We\n // don't rollback them.\n const error = `Unable to create multichain account group for index: ${groupIndex}`;\n\n let warn = `${error}:`;\n for (const result of results) {\n if (result.status === 'rejected') {\n warn += `\\n- ${result.reason}`;\n }\n }\n console.warn(warn);\n\n throw new Error(error);\n }\n\n // Because of the :accountAdded automatic sync, we might already have created the\n // group, so we first try to get it.\n group = this.getMultichainAccountGroup(groupIndex);\n if (!group) {\n // If for some reason it's still not created, we're creating it explicitly now:\n group = new MultichainAccountGroup({\n wallet: this,\n providers: this.#providers,\n groupIndex,\n });\n }\n\n // Register the account to our internal map.\n this.#accountGroups.set(groupIndex, group); // `group` cannot be undefined here.\n\n return group;\n }\n\n /**\n * Creates the next multichain account group.\n *\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for the next group index available.\n */\n async createNextMultichainAccountGroup(): Promise<\n MultichainAccountGroup<Account>\n > {\n return this.createMultichainAccountGroup(this.getNextGroupIndex());\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainAccountWallet.cjs","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAOA,uDAI+B;AAC/B,uDAAgE;AAChE,uDAA0D;AAM1D,yEAAkE;AAElE;;;GAGG;AACH,MAAa,uBAAuB;IAYlC,YAAY,EACV,SAAS,EACT,aAAa,GAId;QAdQ,8CAA+B;QAE/B,qDAAuC;QAEvC,yDAAgC;QAEhC,oDAAwD;QAS/D,uBAAA,IAAI,+BAAO,IAAA,yCAA2B,EAAC,aAAa,CAAC,MAAA,CAAC;QACtD,uBAAA,IAAI,sCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,0CAAkB,aAAa,MAAA,CAAC;QACpC,uBAAA,IAAI,qCAAa,IAAI,GAAG,EAAE,MAAA,CAAC;QAE3B,2BAA2B;QAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACH,IAAI;QACF,KAAK,MAAM,QAAQ,IAAI,uBAAA,IAAI,0CAAW,EAAE;YACtC,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE;gBAC5C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;gBAEpC,+BAA+B;gBAC/B,IAAI,OAAO,CAAC,EAAE,KAAK,IAAI,CAAC,aAAa,EAAE;oBACrC,SAAS;iBACV;gBAED,gDAAgD;gBAChD,IAAI,iBAAiB,GAAG,uBAAA,IAAI,yCAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC/D,IAAI,CAAC,iBAAiB,EAAE;oBACtB,iBAAiB,GAAG,IAAI,+CAAsB,CAAU;wBACtD,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,MAAM,EAAE,IAAI;wBACZ,SAAS,EAAE,uBAAA,IAAI,0CAAW;qBAC3B,CAAC,CAAC;oBAEH,uBAAA,IAAI,yCAAU,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;iBAC3D;aACF;SACF;QAED,oDAAoD;QACpD,KAAK,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC,IAAI,uBAAA,IAAI,yCAAU,CAAC,OAAO,EAAE,EAAE;YACtE,iBAAiB,CAAC,IAAI,EAAE,CAAC;YAEzB,oCAAoC;YACpC,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,EAAE;gBACpC,uBAAA,IAAI,yCAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;aACnC;SACF;IACH,CAAC;IAED;;;;OAIG;IACH,IAAI,EAAE;QACJ,OAAO,uBAAA,IAAI,mCAAI,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACH,IAAI,IAAI;QACN,OAAO,+BAAiB,CAAC,OAAO,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,IAAI,aAAa;QACf,OAAO,uBAAA,IAAI,8CAAe,CAAC;IAC7B,CAAC;IAED;;;;;;OAMG;IACH,eAAe,CACb,EAAkB;QAElB,0DAA0D;QAC1D,IAAI,EAAE,KAAK,IAAA,qCAAuB,EAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YAC3C,OAAO,uBAAA,IAAI,yCAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC9B;QAED,6DAA6D;QAC7D,4BAA4B;QAC5B,IAAI,CAAC,IAAA,wCAA0B,EAAC,EAAE,CAAC,EAAE;YACnC,OAAO,SAAS,CAAC;SAClB;QAED,MAAM,UAAU,GAAG,IAAA,kDAAyC,EAAC,EAAE,CAAC,CAAC;QACjE,OAAO,uBAAA,IAAI,yCAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED;;;;OAIG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,0BAA0B,EAAE,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,yBAAyB,CACvB,UAAkB;QAElB,OAAO,uBAAA,IAAI,yCAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED;;;;OAIG;IACH,0BAA0B;QACxB,OAAO,KAAK,CAAC,IAAI,CAAC,uBAAA,IAAI,yCAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,2BAA2B;IACzE,CAAC;CACF;AAtJD,0DAsJC","sourcesContent":["import type {\n Bip44Account,\n MultichainAccountWalletId,\n MultichainAccountWallet as MultichainAccountWalletDefinition,\n} from '@metamask/account-api';\nimport type { AccountGroupId } from '@metamask/account-api';\nimport type { AccountProvider } from '@metamask/account-api';\nimport {\n getGroupIndexFromMultichainAccountId as getGroupIndexFromMultichainAccountGroupId,\n isMultichainAccountGroupId,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport { toDefaultAccountGroupId } from '@metamask/account-api';\nimport { AccountWalletType } from '@metamask/account-api';\nimport {\n type EntropySourceId,\n type KeyringAccount,\n} from '@metamask/keyring-api';\n\nimport { MultichainAccountGroup } from './MultichainAccountGroup';\n\n/**\n * A multichain account wallet that holds multiple multichain accounts (one multichain account per\n * group index).\n */\nexport class MultichainAccountWallet<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountWalletDefinition<Account>\n{\n readonly #id: MultichainAccountWalletId;\n\n readonly #providers: AccountProvider<Account>[];\n\n readonly #entropySource: EntropySourceId;\n\n readonly #accounts: Map<number, MultichainAccountGroup<Account>>;\n\n constructor({\n providers,\n entropySource,\n }: {\n providers: AccountProvider<Account>[];\n entropySource: EntropySourceId;\n }) {\n this.#id = toMultichainAccountWalletId(entropySource);\n this.#providers = providers;\n this.#entropySource = entropySource;\n this.#accounts = new Map();\n\n // Initial synchronization.\n this.sync();\n }\n\n /**\n * Force wallet synchronization.\n *\n * This can be used if account providers got new accounts that the wallet\n * doesn't know about.\n */\n sync(): void {\n for (const provider of this.#providers) {\n for (const account of provider.getAccounts()) {\n const { entropy } = account.options;\n\n // Filter for this wallet only.\n if (entropy.id !== this.entropySource) {\n continue;\n }\n\n // This multichain account might exists already.\n let multichainAccount = this.#accounts.get(entropy.groupIndex);\n if (!multichainAccount) {\n multichainAccount = new MultichainAccountGroup<Account>({\n groupIndex: entropy.groupIndex,\n wallet: this,\n providers: this.#providers,\n });\n\n this.#accounts.set(entropy.groupIndex, multichainAccount);\n }\n }\n }\n\n // Now force-sync all remaining multichain accounts.\n for (const [groupIndex, multichainAccount] of this.#accounts.entries()) {\n multichainAccount.sync();\n\n // Clean up old multichain accounts.\n if (!multichainAccount.hasAccounts()) {\n this.#accounts.delete(groupIndex);\n }\n }\n }\n\n /**\n * Gets the multichain account wallet ID.\n *\n * @returns The multichain account wallet ID.\n */\n get id(): MultichainAccountWalletId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.\n *\n * @returns The multichain account wallet type.\n */\n get type(): AccountWalletType.Entropy {\n return AccountWalletType.Entropy;\n }\n\n /**\n * Gets the multichain account wallet entropy source.\n *\n * @returns The multichain account wallet entropy source.\n */\n get entropySource(): EntropySourceId {\n return this.#entropySource;\n }\n\n /**\n * Gets multichain account for a given ID.\n * The default group ID will default to the multichain account with index 0.\n *\n * @param id - Account group ID.\n * @returns Account group.\n */\n getAccountGroup(\n id: AccountGroupId,\n ): MultichainAccountGroup<Account> | undefined {\n // We consider the \"default case\" to be mapped to index 0.\n if (id === toDefaultAccountGroupId(this.id)) {\n return this.#accounts.get(0);\n }\n\n // If it is not a valid ID, we cannot extract the group index\n // from it, so we fail fast.\n if (!isMultichainAccountGroupId(id)) {\n return undefined;\n }\n\n const groupIndex = getGroupIndexFromMultichainAccountGroupId(id);\n return this.#accounts.get(groupIndex);\n }\n\n /**\n * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.\n *\n * @returns The multichain accounts.\n */\n getAccountGroups(): MultichainAccountGroup<Account>[] {\n return this.getMultichainAccountGroups();\n }\n\n /**\n * Gets multichain account group for a given index.\n *\n * @param groupIndex - Multichain account index.\n * @returns The multichain account associated with the given index.\n */\n getMultichainAccountGroup(\n groupIndex: number,\n ): MultichainAccountGroup<Account> | undefined {\n return this.#accounts.get(groupIndex);\n }\n\n /**\n * Gets all multichain account groups.\n *\n * @returns The multichain accounts.\n */\n getMultichainAccountGroups(): MultichainAccountGroup<Account>[] {\n return Array.from(this.#accounts.values()); // TODO: Prevent copy here.\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
- import { AccountWalletType } from "@metamask/account-api";
2
1
  import type { Bip44Account, MultichainAccountWalletId, MultichainAccountWallet as MultichainAccountWalletDefinition } from "@metamask/account-api";
3
2
  import type { AccountGroupId } from "@metamask/account-api";
4
3
  import type { AccountProvider } from "@metamask/account-api";
4
+ import { AccountWalletType } from "@metamask/account-api";
5
5
  import { type EntropySourceId, type KeyringAccount } from "@metamask/keyring-api";
6
6
  import { MultichainAccountGroup } from "./MultichainAccountGroup.cjs";
7
7
  /**
@@ -66,26 +66,5 @@ export declare class MultichainAccountWallet<Account extends Bip44Account<Keyrin
66
66
  * @returns The multichain accounts.
67
67
  */
68
68
  getMultichainAccountGroups(): MultichainAccountGroup<Account>[];
69
- /**
70
- * Gets next group index for this wallet.
71
- *
72
- * @returns The next group index of this wallet.
73
- */
74
- getNextGroupIndex(): number;
75
- /**
76
- * Creates a multichain account group for a given group index.
77
- *
78
- * @param groupIndex - The group index to use.
79
- * @throws If any of the account providers fails to create their accounts.
80
- * @returns The multichain account group for this group index.
81
- */
82
- createMultichainAccountGroup(groupIndex: number): Promise<MultichainAccountGroup<Account>>;
83
- /**
84
- * Creates the next multichain account group.
85
- *
86
- * @throws If any of the account providers fails to create their accounts.
87
- * @returns The multichain account group for the next group index available.
88
- */
89
- createNextMultichainAccountGroup(): Promise<MultichainAccountGroup<Account>>;
90
69
  }
91
70
  //# sourceMappingURL=MultichainAccountWallet.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountWallet.d.cts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC7D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAE/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAElE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAUzC,EACV,SAAS,EACT,aAAa,GACd,EAAE;QACD,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,aAAa,EAAE,eAAe,CAAC;KAChC;IAUD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAgDZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAI/D;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAU3B;;;;;;OAMG;IACG,4BAA4B,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAoF3C;;;;;OAKG;IACG,gCAAgC,IAAI,OAAO,CAC/C,sBAAsB,CAAC,OAAO,CAAC,CAChC;CAGF"}
1
+ {"version":3,"file":"MultichainAccountWallet.d.cts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC7D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAO7D,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAE/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAElE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAUzC,EACV,SAAS,EACT,aAAa,GACd,EAAE;QACD,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,aAAa,EAAE,eAAe,CAAC;KAChC;IAUD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAmCZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;CAGhE"}
@@ -1,7 +1,7 @@
1
- import { AccountWalletType } from "@metamask/account-api";
2
1
  import type { Bip44Account, MultichainAccountWalletId, MultichainAccountWallet as MultichainAccountWalletDefinition } from "@metamask/account-api";
3
2
  import type { AccountGroupId } from "@metamask/account-api";
4
3
  import type { AccountProvider } from "@metamask/account-api";
4
+ import { AccountWalletType } from "@metamask/account-api";
5
5
  import { type EntropySourceId, type KeyringAccount } from "@metamask/keyring-api";
6
6
  import { MultichainAccountGroup } from "./MultichainAccountGroup.mjs";
7
7
  /**
@@ -66,26 +66,5 @@ export declare class MultichainAccountWallet<Account extends Bip44Account<Keyrin
66
66
  * @returns The multichain accounts.
67
67
  */
68
68
  getMultichainAccountGroups(): MultichainAccountGroup<Account>[];
69
- /**
70
- * Gets next group index for this wallet.
71
- *
72
- * @returns The next group index of this wallet.
73
- */
74
- getNextGroupIndex(): number;
75
- /**
76
- * Creates a multichain account group for a given group index.
77
- *
78
- * @param groupIndex - The group index to use.
79
- * @throws If any of the account providers fails to create their accounts.
80
- * @returns The multichain account group for this group index.
81
- */
82
- createMultichainAccountGroup(groupIndex: number): Promise<MultichainAccountGroup<Account>>;
83
- /**
84
- * Creates the next multichain account group.
85
- *
86
- * @throws If any of the account providers fails to create their accounts.
87
- * @returns The multichain account group for the next group index available.
88
- */
89
- createNextMultichainAccountGroup(): Promise<MultichainAccountGroup<Account>>;
90
69
  }
91
70
  //# sourceMappingURL=MultichainAccountWallet.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountWallet.d.mts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC7D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAE/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAElE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAUzC,EACV,SAAS,EACT,aAAa,GACd,EAAE;QACD,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,aAAa,EAAE,eAAe,CAAC;KAChC;IAUD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAgDZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAI/D;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAU3B;;;;;;OAMG;IACG,4BAA4B,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAoF3C;;;;;OAKG;IACG,gCAAgC,IAAI,OAAO,CAC/C,sBAAsB,CAAC,OAAO,CAAC,CAChC;CAGF"}
1
+ {"version":3,"file":"MultichainAccountWallet.d.mts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC7D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAO7D,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAE/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAElE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAUzC,EACV,SAAS,EACT,aAAa,GACd,EAAE;QACD,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,aAAa,EAAE,eAAe,CAAC;KAChC;IAUD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAmCZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;CAGhE"}
@@ -9,8 +9,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _MultichainAccountWallet_id, _MultichainAccountWallet_providers, _MultichainAccountWallet_entropySource, _MultichainAccountWallet_accountGroups;
13
- import { getGroupIndexFromMultichainAccountGroupId, isMultichainAccountGroupId, toMultichainAccountWalletId } from "@metamask/account-api";
12
+ var _MultichainAccountWallet_id, _MultichainAccountWallet_providers, _MultichainAccountWallet_entropySource, _MultichainAccountWallet_accounts;
13
+ import { getGroupIndexFromMultichainAccountId as getGroupIndexFromMultichainAccountGroupId, isMultichainAccountGroupId, toMultichainAccountWalletId } from "@metamask/account-api";
14
14
  import { toDefaultAccountGroupId } from "@metamask/account-api";
15
15
  import { AccountWalletType } from "@metamask/account-api";
16
16
  import { MultichainAccountGroup } from "./MultichainAccountGroup.mjs";
@@ -23,11 +23,11 @@ export class MultichainAccountWallet {
23
23
  _MultichainAccountWallet_id.set(this, void 0);
24
24
  _MultichainAccountWallet_providers.set(this, void 0);
25
25
  _MultichainAccountWallet_entropySource.set(this, void 0);
26
- _MultichainAccountWallet_accountGroups.set(this, void 0);
26
+ _MultichainAccountWallet_accounts.set(this, void 0);
27
27
  __classPrivateFieldSet(this, _MultichainAccountWallet_id, toMultichainAccountWalletId(entropySource), "f");
28
28
  __classPrivateFieldSet(this, _MultichainAccountWallet_providers, providers, "f");
29
29
  __classPrivateFieldSet(this, _MultichainAccountWallet_entropySource, entropySource, "f");
30
- __classPrivateFieldSet(this, _MultichainAccountWallet_accountGroups, new Map(), "f");
30
+ __classPrivateFieldSet(this, _MultichainAccountWallet_accounts, new Map(), "f");
31
31
  // Initial synchronization.
32
32
  this.sync();
33
33
  }
@@ -46,32 +46,23 @@ export class MultichainAccountWallet {
46
46
  continue;
47
47
  }
48
48
  // This multichain account might exists already.
49
- let multichainAccount = __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").get(entropy.groupIndex);
49
+ let multichainAccount = __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(entropy.groupIndex);
50
50
  if (!multichainAccount) {
51
51
  multichainAccount = new MultichainAccountGroup({
52
52
  groupIndex: entropy.groupIndex,
53
53
  wallet: this,
54
54
  providers: __classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f"),
55
55
  });
56
- // This existing multichain account group might differ from the
57
- // `createMultichainAccountGroup` behavior. When creating a new
58
- // group, we expect the providers to all succeed. But here, we're
59
- // just fetching the account lists from them, so this group might
60
- // not be "aligned" yet (e.g having a missing Solana account).
61
- //
62
- // Since "aligning" is an async operation, it would have to be run
63
- // after the first-sync.
64
- // TODO: Implement align mechanism to create "missing" accounts.
65
- __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").set(entropy.groupIndex, multichainAccount);
56
+ __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").set(entropy.groupIndex, multichainAccount);
66
57
  }
67
58
  }
68
59
  }
69
60
  // Now force-sync all remaining multichain accounts.
70
- for (const [groupIndex, multichainAccount,] of __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").entries()) {
61
+ for (const [groupIndex, multichainAccount] of __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").entries()) {
71
62
  multichainAccount.sync();
72
63
  // Clean up old multichain accounts.
73
64
  if (!multichainAccount.hasAccounts()) {
74
- __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").delete(groupIndex);
65
+ __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").delete(groupIndex);
75
66
  }
76
67
  }
77
68
  }
@@ -109,7 +100,7 @@ export class MultichainAccountWallet {
109
100
  getAccountGroup(id) {
110
101
  // We consider the "default case" to be mapped to index 0.
111
102
  if (id === toDefaultAccountGroupId(this.id)) {
112
- return __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").get(0);
103
+ return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(0);
113
104
  }
114
105
  // If it is not a valid ID, we cannot extract the group index
115
106
  // from it, so we fail fast.
@@ -117,7 +108,7 @@ export class MultichainAccountWallet {
117
108
  return undefined;
118
109
  }
119
110
  const groupIndex = getGroupIndexFromMultichainAccountGroupId(id);
120
- return __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").get(groupIndex);
111
+ return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(groupIndex);
121
112
  }
122
113
  /**
123
114
  * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.
@@ -134,7 +125,7 @@ export class MultichainAccountWallet {
134
125
  * @returns The multichain account associated with the given index.
135
126
  */
136
127
  getMultichainAccountGroup(groupIndex) {
137
- return __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").get(groupIndex);
128
+ return __classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").get(groupIndex);
138
129
  }
139
130
  /**
140
131
  * Gets all multichain account groups.
@@ -142,101 +133,8 @@ export class MultichainAccountWallet {
142
133
  * @returns The multichain accounts.
143
134
  */
144
135
  getMultichainAccountGroups() {
145
- return Array.from(__classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").values()); // TODO: Prevent copy here.
146
- }
147
- /**
148
- * Gets next group index for this wallet.
149
- *
150
- * @returns The next group index of this wallet.
151
- */
152
- getNextGroupIndex() {
153
- // We do not check for gaps.
154
- return (Math.max(-1, // So it will default to 0 if no groups.
155
- ...__classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").keys()) + 1);
156
- }
157
- /**
158
- * Creates a multichain account group for a given group index.
159
- *
160
- * @param groupIndex - The group index to use.
161
- * @throws If any of the account providers fails to create their accounts.
162
- * @returns The multichain account group for this group index.
163
- */
164
- async createMultichainAccountGroup(groupIndex) {
165
- const nextGroupIndex = this.getNextGroupIndex();
166
- if (groupIndex > nextGroupIndex) {
167
- throw new Error(`You cannot use a group index that is higher than the next available one: expected <=${nextGroupIndex}, got ${groupIndex}`);
168
- }
169
- let group = this.getMultichainAccountGroup(groupIndex);
170
- if (group) {
171
- // If the group already exists, we just `sync` it and returns the same
172
- // reference.
173
- group.sync();
174
- return group;
175
- }
176
- const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f").map((provider) => provider.createAccounts({
177
- entropySource: __classPrivateFieldGet(this, _MultichainAccountWallet_entropySource, "f"),
178
- groupIndex,
179
- })));
180
- // --------------------------------------------------------------------------------
181
- // READ THIS CAREFULLY:
182
- //
183
- // Since we're not "fully supporting multichain" for now, we still rely on single
184
- // :accountCreated events to sync multichain account groups and wallets. Which means
185
- // that even if of the provider fails, some accounts will still be created on some
186
- // other providers and will become "available" on the `AccountsController`, like:
187
- //
188
- // 1. Creating a multichain account group for index 1
189
- // 2. EvmAccountProvider.createAccounts returns the EVM account for index 1
190
- // * AccountsController WILL fire :accountCreated for this account
191
- // * This account WILL BE "available" on the AccountsController state
192
- // 3. SolAccountProvider.createAccounts fails to create a Solana account for index 1
193
- // * AccountsController WON't fire :accountCreated for this account
194
- // * This account WON'T be "available" on the Account
195
- // 4. MultichainAccountService will receive a :accountCreated for the EVM account from
196
- // step 2 and will create a new multichain account group for index 1, but it won't
197
- // receive any event for the Solana account of this group. Thus, this group won't be
198
- // "aligned" (missing "blockchain account" on this group).
199
- //
200
- // --------------------------------------------------------------------------------
201
- // If any of the provider failed to create their accounts, then we consider the
202
- // multichain account group to have failed too.
203
- if (results.some((result) => result.status === 'rejected')) {
204
- // NOTE: Some accounts might still have been created on other account providers. We
205
- // don't rollback them.
206
- const error = `Unable to create multichain account group for index: ${groupIndex}`;
207
- let warn = `${error}:`;
208
- for (const result of results) {
209
- if (result.status === 'rejected') {
210
- warn += `\n- ${result.reason}`;
211
- }
212
- }
213
- console.warn(warn);
214
- throw new Error(error);
215
- }
216
- // Because of the :accountAdded automatic sync, we might already have created the
217
- // group, so we first try to get it.
218
- group = this.getMultichainAccountGroup(groupIndex);
219
- if (!group) {
220
- // If for some reason it's still not created, we're creating it explicitly now:
221
- group = new MultichainAccountGroup({
222
- wallet: this,
223
- providers: __classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f"),
224
- groupIndex,
225
- });
226
- }
227
- // Register the account to our internal map.
228
- __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").set(groupIndex, group); // `group` cannot be undefined here.
229
- return group;
230
- }
231
- /**
232
- * Creates the next multichain account group.
233
- *
234
- * @throws If any of the account providers fails to create their accounts.
235
- * @returns The multichain account group for the next group index available.
236
- */
237
- async createNextMultichainAccountGroup() {
238
- return this.createMultichainAccountGroup(this.getNextGroupIndex());
136
+ return Array.from(__classPrivateFieldGet(this, _MultichainAccountWallet_accounts, "f").values()); // TODO: Prevent copy here.
239
137
  }
240
138
  }
241
- _MultichainAccountWallet_id = new WeakMap(), _MultichainAccountWallet_providers = new WeakMap(), _MultichainAccountWallet_entropySource = new WeakMap(), _MultichainAccountWallet_accountGroups = new WeakMap();
139
+ _MultichainAccountWallet_id = new WeakMap(), _MultichainAccountWallet_providers = new WeakMap(), _MultichainAccountWallet_entropySource = new WeakMap(), _MultichainAccountWallet_accounts = new WeakMap();
242
140
  //# sourceMappingURL=MultichainAccountWallet.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountWallet.mjs","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getGroupIndexFromMultichainAccountGroupId,\n isMultichainAccountGroupId,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport { toDefaultAccountGroupId } from '@metamask/account-api';\nimport { AccountWalletType } from '@metamask/account-api';\nimport type {\n Bip44Account,\n MultichainAccountWalletId,\n MultichainAccountWallet as MultichainAccountWalletDefinition,\n} from '@metamask/account-api';\nimport type { AccountGroupId } from '@metamask/account-api';\nimport type { AccountProvider } from '@metamask/account-api';\nimport {\n type EntropySourceId,\n type KeyringAccount,\n} from '@metamask/keyring-api';\n\nimport { MultichainAccountGroup } from './MultichainAccountGroup';\n\n/**\n * A multichain account wallet that holds multiple multichain accounts (one multichain account per\n * group index).\n */\nexport class MultichainAccountWallet<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountWalletDefinition<Account>\n{\n readonly #id: MultichainAccountWalletId;\n\n readonly #providers: AccountProvider<Account>[];\n\n readonly #entropySource: EntropySourceId;\n\n readonly #accountGroups: Map<number, MultichainAccountGroup<Account>>;\n\n constructor({\n providers,\n entropySource,\n }: {\n providers: AccountProvider<Account>[];\n entropySource: EntropySourceId;\n }) {\n this.#id = toMultichainAccountWalletId(entropySource);\n this.#providers = providers;\n this.#entropySource = entropySource;\n this.#accountGroups = new Map();\n\n // Initial synchronization.\n this.sync();\n }\n\n /**\n * Force wallet synchronization.\n *\n * This can be used if account providers got new accounts that the wallet\n * doesn't know about.\n */\n sync(): void {\n for (const provider of this.#providers) {\n for (const account of provider.getAccounts()) {\n const { entropy } = account.options;\n\n // Filter for this wallet only.\n if (entropy.id !== this.entropySource) {\n continue;\n }\n\n // This multichain account might exists already.\n let multichainAccount = this.#accountGroups.get(entropy.groupIndex);\n if (!multichainAccount) {\n multichainAccount = new MultichainAccountGroup<Account>({\n groupIndex: entropy.groupIndex,\n wallet: this,\n providers: this.#providers,\n });\n\n // This existing multichain account group might differ from the\n // `createMultichainAccountGroup` behavior. When creating a new\n // group, we expect the providers to all succeed. But here, we're\n // just fetching the account lists from them, so this group might\n // not be \"aligned\" yet (e.g having a missing Solana account).\n //\n // Since \"aligning\" is an async operation, it would have to be run\n // after the first-sync.\n // TODO: Implement align mechanism to create \"missing\" accounts.\n\n this.#accountGroups.set(entropy.groupIndex, multichainAccount);\n }\n }\n }\n\n // Now force-sync all remaining multichain accounts.\n for (const [\n groupIndex,\n multichainAccount,\n ] of this.#accountGroups.entries()) {\n multichainAccount.sync();\n\n // Clean up old multichain accounts.\n if (!multichainAccount.hasAccounts()) {\n this.#accountGroups.delete(groupIndex);\n }\n }\n }\n\n /**\n * Gets the multichain account wallet ID.\n *\n * @returns The multichain account wallet ID.\n */\n get id(): MultichainAccountWalletId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.\n *\n * @returns The multichain account wallet type.\n */\n get type(): AccountWalletType.Entropy {\n return AccountWalletType.Entropy;\n }\n\n /**\n * Gets the multichain account wallet entropy source.\n *\n * @returns The multichain account wallet entropy source.\n */\n get entropySource(): EntropySourceId {\n return this.#entropySource;\n }\n\n /**\n * Gets multichain account for a given ID.\n * The default group ID will default to the multichain account with index 0.\n *\n * @param id - Account group ID.\n * @returns Account group.\n */\n getAccountGroup(\n id: AccountGroupId,\n ): MultichainAccountGroup<Account> | undefined {\n // We consider the \"default case\" to be mapped to index 0.\n if (id === toDefaultAccountGroupId(this.id)) {\n return this.#accountGroups.get(0);\n }\n\n // If it is not a valid ID, we cannot extract the group index\n // from it, so we fail fast.\n if (!isMultichainAccountGroupId(id)) {\n return undefined;\n }\n\n const groupIndex = getGroupIndexFromMultichainAccountGroupId(id);\n return this.#accountGroups.get(groupIndex);\n }\n\n /**\n * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.\n *\n * @returns The multichain accounts.\n */\n getAccountGroups(): MultichainAccountGroup<Account>[] {\n return this.getMultichainAccountGroups();\n }\n\n /**\n * Gets multichain account group for a given index.\n *\n * @param groupIndex - Multichain account index.\n * @returns The multichain account associated with the given index.\n */\n getMultichainAccountGroup(\n groupIndex: number,\n ): MultichainAccountGroup<Account> | undefined {\n return this.#accountGroups.get(groupIndex);\n }\n\n /**\n * Gets all multichain account groups.\n *\n * @returns The multichain accounts.\n */\n getMultichainAccountGroups(): MultichainAccountGroup<Account>[] {\n return Array.from(this.#accountGroups.values()); // TODO: Prevent copy here.\n }\n\n /**\n * Gets next group index for this wallet.\n *\n * @returns The next group index of this wallet.\n */\n getNextGroupIndex(): number {\n // We do not check for gaps.\n return (\n Math.max(\n -1, // So it will default to 0 if no groups.\n ...this.#accountGroups.keys(),\n ) + 1\n );\n }\n\n /**\n * Creates a multichain account group for a given group index.\n *\n * @param groupIndex - The group index to use.\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for this group index.\n */\n async createMultichainAccountGroup(\n groupIndex: number,\n ): Promise<MultichainAccountGroup<Account>> {\n const nextGroupIndex = this.getNextGroupIndex();\n if (groupIndex > nextGroupIndex) {\n throw new Error(\n `You cannot use a group index that is higher than the next available one: expected <=${nextGroupIndex}, got ${groupIndex}`,\n );\n }\n\n let group = this.getMultichainAccountGroup(groupIndex);\n if (group) {\n // If the group already exists, we just `sync` it and returns the same\n // reference.\n group.sync();\n\n return group;\n }\n\n const results = await Promise.allSettled(\n this.#providers.map((provider) =>\n provider.createAccounts({\n entropySource: this.#entropySource,\n groupIndex,\n }),\n ),\n );\n\n // --------------------------------------------------------------------------------\n // READ THIS CAREFULLY:\n //\n // Since we're not \"fully supporting multichain\" for now, we still rely on single\n // :accountCreated events to sync multichain account groups and wallets. Which means\n // that even if of the provider fails, some accounts will still be created on some\n // other providers and will become \"available\" on the `AccountsController`, like:\n //\n // 1. Creating a multichain account group for index 1\n // 2. EvmAccountProvider.createAccounts returns the EVM account for index 1\n // * AccountsController WILL fire :accountCreated for this account\n // * This account WILL BE \"available\" on the AccountsController state\n // 3. SolAccountProvider.createAccounts fails to create a Solana account for index 1\n // * AccountsController WON't fire :accountCreated for this account\n // * This account WON'T be \"available\" on the Account\n // 4. MultichainAccountService will receive a :accountCreated for the EVM account from\n // step 2 and will create a new multichain account group for index 1, but it won't\n // receive any event for the Solana account of this group. Thus, this group won't be\n // \"aligned\" (missing \"blockchain account\" on this group).\n //\n // --------------------------------------------------------------------------------\n\n // If any of the provider failed to create their accounts, then we consider the\n // multichain account group to have failed too.\n if (results.some((result) => result.status === 'rejected')) {\n // NOTE: Some accounts might still have been created on other account providers. We\n // don't rollback them.\n const error = `Unable to create multichain account group for index: ${groupIndex}`;\n\n let warn = `${error}:`;\n for (const result of results) {\n if (result.status === 'rejected') {\n warn += `\\n- ${result.reason}`;\n }\n }\n console.warn(warn);\n\n throw new Error(error);\n }\n\n // Because of the :accountAdded automatic sync, we might already have created the\n // group, so we first try to get it.\n group = this.getMultichainAccountGroup(groupIndex);\n if (!group) {\n // If for some reason it's still not created, we're creating it explicitly now:\n group = new MultichainAccountGroup({\n wallet: this,\n providers: this.#providers,\n groupIndex,\n });\n }\n\n // Register the account to our internal map.\n this.#accountGroups.set(groupIndex, group); // `group` cannot be undefined here.\n\n return group;\n }\n\n /**\n * Creates the next multichain account group.\n *\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for the next group index available.\n */\n async createNextMultichainAccountGroup(): Promise<\n MultichainAccountGroup<Account>\n > {\n return this.createMultichainAccountGroup(this.getNextGroupIndex());\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainAccountWallet.mjs","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n Bip44Account,\n MultichainAccountWalletId,\n MultichainAccountWallet as MultichainAccountWalletDefinition,\n} from '@metamask/account-api';\nimport type { AccountGroupId } from '@metamask/account-api';\nimport type { AccountProvider } from '@metamask/account-api';\nimport {\n getGroupIndexFromMultichainAccountId as getGroupIndexFromMultichainAccountGroupId,\n isMultichainAccountGroupId,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport { toDefaultAccountGroupId } from '@metamask/account-api';\nimport { AccountWalletType } from '@metamask/account-api';\nimport {\n type EntropySourceId,\n type KeyringAccount,\n} from '@metamask/keyring-api';\n\nimport { MultichainAccountGroup } from './MultichainAccountGroup';\n\n/**\n * A multichain account wallet that holds multiple multichain accounts (one multichain account per\n * group index).\n */\nexport class MultichainAccountWallet<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountWalletDefinition<Account>\n{\n readonly #id: MultichainAccountWalletId;\n\n readonly #providers: AccountProvider<Account>[];\n\n readonly #entropySource: EntropySourceId;\n\n readonly #accounts: Map<number, MultichainAccountGroup<Account>>;\n\n constructor({\n providers,\n entropySource,\n }: {\n providers: AccountProvider<Account>[];\n entropySource: EntropySourceId;\n }) {\n this.#id = toMultichainAccountWalletId(entropySource);\n this.#providers = providers;\n this.#entropySource = entropySource;\n this.#accounts = new Map();\n\n // Initial synchronization.\n this.sync();\n }\n\n /**\n * Force wallet synchronization.\n *\n * This can be used if account providers got new accounts that the wallet\n * doesn't know about.\n */\n sync(): void {\n for (const provider of this.#providers) {\n for (const account of provider.getAccounts()) {\n const { entropy } = account.options;\n\n // Filter for this wallet only.\n if (entropy.id !== this.entropySource) {\n continue;\n }\n\n // This multichain account might exists already.\n let multichainAccount = this.#accounts.get(entropy.groupIndex);\n if (!multichainAccount) {\n multichainAccount = new MultichainAccountGroup<Account>({\n groupIndex: entropy.groupIndex,\n wallet: this,\n providers: this.#providers,\n });\n\n this.#accounts.set(entropy.groupIndex, multichainAccount);\n }\n }\n }\n\n // Now force-sync all remaining multichain accounts.\n for (const [groupIndex, multichainAccount] of this.#accounts.entries()) {\n multichainAccount.sync();\n\n // Clean up old multichain accounts.\n if (!multichainAccount.hasAccounts()) {\n this.#accounts.delete(groupIndex);\n }\n }\n }\n\n /**\n * Gets the multichain account wallet ID.\n *\n * @returns The multichain account wallet ID.\n */\n get id(): MultichainAccountWalletId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.\n *\n * @returns The multichain account wallet type.\n */\n get type(): AccountWalletType.Entropy {\n return AccountWalletType.Entropy;\n }\n\n /**\n * Gets the multichain account wallet entropy source.\n *\n * @returns The multichain account wallet entropy source.\n */\n get entropySource(): EntropySourceId {\n return this.#entropySource;\n }\n\n /**\n * Gets multichain account for a given ID.\n * The default group ID will default to the multichain account with index 0.\n *\n * @param id - Account group ID.\n * @returns Account group.\n */\n getAccountGroup(\n id: AccountGroupId,\n ): MultichainAccountGroup<Account> | undefined {\n // We consider the \"default case\" to be mapped to index 0.\n if (id === toDefaultAccountGroupId(this.id)) {\n return this.#accounts.get(0);\n }\n\n // If it is not a valid ID, we cannot extract the group index\n // from it, so we fail fast.\n if (!isMultichainAccountGroupId(id)) {\n return undefined;\n }\n\n const groupIndex = getGroupIndexFromMultichainAccountGroupId(id);\n return this.#accounts.get(groupIndex);\n }\n\n /**\n * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.\n *\n * @returns The multichain accounts.\n */\n getAccountGroups(): MultichainAccountGroup<Account>[] {\n return this.getMultichainAccountGroups();\n }\n\n /**\n * Gets multichain account group for a given index.\n *\n * @param groupIndex - Multichain account index.\n * @returns The multichain account associated with the given index.\n */\n getMultichainAccountGroup(\n groupIndex: number,\n ): MultichainAccountGroup<Account> | undefined {\n return this.#accounts.get(groupIndex);\n }\n\n /**\n * Gets all multichain account groups.\n *\n * @returns The multichain accounts.\n */\n getMultichainAccountGroups(): MultichainAccountGroup<Account>[] {\n return Array.from(this.#accounts.values()); // TODO: Prevent copy here.\n }\n}\n"]}
package/dist/index.cjs CHANGED
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MultichainAccountService = exports.MultichainAccountGroup = exports.MultichainAccountWallet = exports.SnapAccountProvider = exports.BaseAccountProvider = exports.assertIsBip44Account = void 0;
4
- var providers_1 = require("./providers/index.cjs");
5
- Object.defineProperty(exports, "assertIsBip44Account", { enumerable: true, get: function () { return providers_1.assertIsBip44Account; } });
6
- Object.defineProperty(exports, "BaseAccountProvider", { enumerable: true, get: function () { return providers_1.BaseAccountProvider; } });
7
- Object.defineProperty(exports, "SnapAccountProvider", { enumerable: true, get: function () { return providers_1.SnapAccountProvider; } });
3
+ exports.MultichainAccountService = exports.MultichainAccountGroup = exports.MultichainAccountWallet = void 0;
8
4
  var MultichainAccountWallet_1 = require("./MultichainAccountWallet.cjs");
9
5
  Object.defineProperty(exports, "MultichainAccountWallet", { enumerable: true, get: function () { return MultichainAccountWallet_1.MultichainAccountWallet; } });
10
6
  var MultichainAccountGroup_1 = require("./MultichainAccountGroup.cjs");
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AASA,mDAIqB;AAHnB,iHAAA,oBAAoB,OAAA;AACpB,gHAAA,mBAAmB,OAAA;AACnB,gHAAA,mBAAmB,OAAA;AAErB,yEAAoE;AAA3D,kIAAA,uBAAuB,OAAA;AAChC,uEAAkE;AAAzD,gIAAA,sBAAsB,OAAA;AAC/B,2EAAsE;AAA7D,oIAAA,wBAAwB,OAAA","sourcesContent":["export type {\n MultichainAccountServiceActions,\n MultichainAccountServiceEvents,\n MultichainAccountServiceMessenger,\n MultichainAccountServiceGetMultichainAccountGroupAction,\n MultichainAccountServiceGetMultichainAccountWalletAction,\n MultichainAccountServiceGetMultichainAccountWalletsAction,\n MultichainAccountServiceGetMultichainAccountGroupsAction,\n} from './types';\nexport {\n assertIsBip44Account,\n BaseAccountProvider,\n SnapAccountProvider,\n} from './providers';\nexport { MultichainAccountWallet } from './MultichainAccountWallet';\nexport { MultichainAccountGroup } from './MultichainAccountGroup';\nexport { MultichainAccountService } from './MultichainAccountService';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AASA,yEAAoE;AAA3D,kIAAA,uBAAuB,OAAA;AAChC,uEAAkE;AAAzD,gIAAA,sBAAsB,OAAA;AAC/B,2EAAsE;AAA7D,oIAAA,wBAAwB,OAAA","sourcesContent":["export type {\n MultichainAccountServiceActions,\n MultichainAccountServiceEvents,\n MultichainAccountServiceMessenger,\n MultichainAccountServiceGetMultichainAccountGroupAction,\n MultichainAccountServiceGetMultichainAccountWalletAction,\n MultichainAccountServiceGetMultichainAccountWalletsAction,\n MultichainAccountServiceGetMultichainAccountGroupsAction,\n} from './types';\nexport { MultichainAccountWallet } from './MultichainAccountWallet';\nexport { MultichainAccountGroup } from './MultichainAccountGroup';\nexport { MultichainAccountService } from './MultichainAccountService';\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,4 @@
1
1
  export type { MultichainAccountServiceActions, MultichainAccountServiceEvents, MultichainAccountServiceMessenger, MultichainAccountServiceGetMultichainAccountGroupAction, MultichainAccountServiceGetMultichainAccountWalletAction, MultichainAccountServiceGetMultichainAccountWalletsAction, MultichainAccountServiceGetMultichainAccountGroupsAction, } from "./types.cjs";
2
- export { assertIsBip44Account, BaseAccountProvider, SnapAccountProvider, } from "./providers/index.cjs";
3
2
  export { MultichainAccountWallet } from "./MultichainAccountWallet.cjs";
4
3
  export { MultichainAccountGroup } from "./MultichainAccountGroup.cjs";
5
4
  export { MultichainAccountService } from "./MultichainAccountService.cjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,iCAAiC,EACjC,uDAAuD,EACvD,wDAAwD,EACxD,yDAAyD,EACzD,wDAAwD,GACzD,oBAAgB;AACjB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,GACpB,8BAAoB;AACrB,OAAO,EAAE,uBAAuB,EAAE,sCAAkC;AACpE,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAClE,OAAO,EAAE,wBAAwB,EAAE,uCAAmC"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,iCAAiC,EACjC,uDAAuD,EACvD,wDAAwD,EACxD,yDAAyD,EACzD,wDAAwD,GACzD,oBAAgB;AACjB,OAAO,EAAE,uBAAuB,EAAE,sCAAkC;AACpE,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAClE,OAAO,EAAE,wBAAwB,EAAE,uCAAmC"}