@metamask-previews/multichain-account-service 5.0.0-preview-4a66b658 → 5.0.0-preview-1137ade3

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 (96) hide show
  1. package/CHANGELOG.md +0 -25
  2. package/dist/MultichainAccountGroup.cjs +45 -84
  3. package/dist/MultichainAccountGroup.cjs.map +1 -1
  4. package/dist/MultichainAccountGroup.d.cts +4 -17
  5. package/dist/MultichainAccountGroup.d.cts.map +1 -1
  6. package/dist/MultichainAccountGroup.d.mts +4 -17
  7. package/dist/MultichainAccountGroup.d.mts.map +1 -1
  8. package/dist/MultichainAccountGroup.mjs +45 -84
  9. package/dist/MultichainAccountGroup.mjs.map +1 -1
  10. package/dist/MultichainAccountService.cjs +113 -152
  11. package/dist/MultichainAccountService.cjs.map +1 -1
  12. package/dist/MultichainAccountService.d.cts +20 -48
  13. package/dist/MultichainAccountService.d.cts.map +1 -1
  14. package/dist/MultichainAccountService.d.mts +20 -48
  15. package/dist/MultichainAccountService.d.mts.map +1 -1
  16. package/dist/MultichainAccountService.mjs +114 -153
  17. package/dist/MultichainAccountService.mjs.map +1 -1
  18. package/dist/MultichainAccountWallet.cjs +123 -108
  19. package/dist/MultichainAccountWallet.cjs.map +1 -1
  20. package/dist/MultichainAccountWallet.d.cts +4 -5
  21. package/dist/MultichainAccountWallet.d.cts.map +1 -1
  22. package/dist/MultichainAccountWallet.d.mts +4 -5
  23. package/dist/MultichainAccountWallet.d.mts.map +1 -1
  24. package/dist/MultichainAccountWallet.mjs +123 -108
  25. package/dist/MultichainAccountWallet.mjs.map +1 -1
  26. package/dist/providers/AccountProviderWrapper.cjs +0 -18
  27. package/dist/providers/AccountProviderWrapper.cjs.map +1 -1
  28. package/dist/providers/AccountProviderWrapper.d.cts +0 -12
  29. package/dist/providers/AccountProviderWrapper.d.cts.map +1 -1
  30. package/dist/providers/AccountProviderWrapper.d.mts +0 -12
  31. package/dist/providers/AccountProviderWrapper.d.mts.map +1 -1
  32. package/dist/providers/AccountProviderWrapper.mjs +0 -18
  33. package/dist/providers/AccountProviderWrapper.mjs.map +1 -1
  34. package/dist/providers/BaseBip44AccountProvider.cjs +20 -45
  35. package/dist/providers/BaseBip44AccountProvider.cjs.map +1 -1
  36. package/dist/providers/BaseBip44AccountProvider.d.cts +6 -58
  37. package/dist/providers/BaseBip44AccountProvider.d.cts.map +1 -1
  38. package/dist/providers/BaseBip44AccountProvider.d.mts +6 -58
  39. package/dist/providers/BaseBip44AccountProvider.d.mts.map +1 -1
  40. package/dist/providers/BaseBip44AccountProvider.mjs +20 -45
  41. package/dist/providers/BaseBip44AccountProvider.mjs.map +1 -1
  42. package/dist/providers/BtcAccountProvider.cjs +0 -1
  43. package/dist/providers/BtcAccountProvider.cjs.map +1 -1
  44. package/dist/providers/BtcAccountProvider.d.cts.map +1 -1
  45. package/dist/providers/BtcAccountProvider.d.mts.map +1 -1
  46. package/dist/providers/BtcAccountProvider.mjs +0 -1
  47. package/dist/providers/BtcAccountProvider.mjs.map +1 -1
  48. package/dist/providers/EvmAccountProvider.cjs +5 -39
  49. package/dist/providers/EvmAccountProvider.cjs.map +1 -1
  50. package/dist/providers/EvmAccountProvider.d.cts +0 -8
  51. package/dist/providers/EvmAccountProvider.d.cts.map +1 -1
  52. package/dist/providers/EvmAccountProvider.d.mts +0 -8
  53. package/dist/providers/EvmAccountProvider.d.mts.map +1 -1
  54. package/dist/providers/EvmAccountProvider.mjs +5 -39
  55. package/dist/providers/EvmAccountProvider.mjs.map +1 -1
  56. package/dist/providers/SolAccountProvider.cjs +0 -4
  57. package/dist/providers/SolAccountProvider.cjs.map +1 -1
  58. package/dist/providers/SolAccountProvider.d.cts.map +1 -1
  59. package/dist/providers/SolAccountProvider.d.mts.map +1 -1
  60. package/dist/providers/SolAccountProvider.mjs +0 -4
  61. package/dist/providers/SolAccountProvider.mjs.map +1 -1
  62. package/dist/providers/TrxAccountProvider.cjs +0 -1
  63. package/dist/providers/TrxAccountProvider.cjs.map +1 -1
  64. package/dist/providers/TrxAccountProvider.d.cts.map +1 -1
  65. package/dist/providers/TrxAccountProvider.d.mts.map +1 -1
  66. package/dist/providers/TrxAccountProvider.mjs +0 -1
  67. package/dist/providers/TrxAccountProvider.mjs.map +1 -1
  68. package/dist/tests/messenger.cjs +0 -4
  69. package/dist/tests/messenger.cjs.map +1 -1
  70. package/dist/tests/messenger.d.cts.map +1 -1
  71. package/dist/tests/messenger.d.mts.map +1 -1
  72. package/dist/tests/messenger.mjs +0 -4
  73. package/dist/tests/messenger.mjs.map +1 -1
  74. package/dist/tests/providers.cjs +7 -62
  75. package/dist/tests/providers.cjs.map +1 -1
  76. package/dist/tests/providers.d.cts +3 -17
  77. package/dist/tests/providers.d.cts.map +1 -1
  78. package/dist/tests/providers.d.mts +3 -17
  79. package/dist/tests/providers.d.mts.map +1 -1
  80. package/dist/tests/providers.mjs +6 -60
  81. package/dist/tests/providers.mjs.map +1 -1
  82. package/dist/types.cjs.map +1 -1
  83. package/dist/types.d.cts +4 -8
  84. package/dist/types.d.cts.map +1 -1
  85. package/dist/types.d.mts +4 -8
  86. package/dist/types.d.mts.map +1 -1
  87. package/dist/types.mjs.map +1 -1
  88. package/dist/utils.cjs +11 -1
  89. package/dist/utils.cjs.map +1 -1
  90. package/dist/utils.d.cts +1 -0
  91. package/dist/utils.d.cts.map +1 -1
  92. package/dist/utils.d.mts +1 -0
  93. package/dist/utils.d.mts.map +1 -1
  94. package/dist/utils.mjs +9 -0
  95. package/dist/utils.mjs.map +1 -1
  96. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -7,17 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ### Added
11
-
12
- - **BREAKING** A performance refactor was made around all the classes in this package ([#6654](https://github.com/MetaMask/core/pull/6654))
13
- - Add logic in the `createMultichainAccountWallet` method in `MultichainAccountService` so that it can handle all entry points: importing an SRP, recovering a vault and creating a new vault.
14
- - Add a `getAccountIds` method which returns all the account ids pertaining to a group.
15
- - Add an `addAccounts` method on the `BaseBip44AccountProvider` class which keeps track of all the account IDs that pertain to it.
16
-
17
- ### Changed
18
-
19
- - Bump `@metamask/accounts-controller` from `^35.0.0` to `^35.0.2` ([#7604](https://github.com/MetaMask/core/pull/7604), [#7642](https://github.com/MetaMask/core/pull/7642))
20
-
21
10
  ## [5.0.0]
22
11
 
23
12
  ### Added
@@ -119,22 +108,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
119
108
 
120
109
  ### Changed
121
110
 
122
- - **BREAKING** A performance refactor was made around all the classes in this package ([#6654](https://github.com/MetaMask/core/pull/6654))
123
- - The `MultichainAccountService` is refactored to construct a top level service state for its `init` function, this state is passed down to the `MultichainAccountWallet` and `MultichainAccountGroup` classes in slices for them to construct their internal states.
124
- - Additional state is generated at the entry points where it needs to be updated i.e. `createMultichainAccountGroup`, `discoverAccounts` and `alignAccounts`.
125
- - We no longer prevent group creation if some providers' `createAccounts` calls fail during group creation, only if they all fail.
126
- - The `getAccounts` method in the `BaseBip44AccountProvider` class no longer relies on fetching the entire list of internal accounts from the `AccountsController`, instead it gets the specific accounts that it stores in its internal accounts list.
127
- - The `EvmAccountProvider` no longer fetches from the `AccountController` to get an account for its ID, we deterministically get the associated account ID through `getUUIDFromAddressOfNormalAccount`.
128
- - The `EvmAccountProvider` now uses the `getAccount` method from the `AccountsController` when fetching an account after account creation as it is more efficient.
129
111
  - Bump `@metamask/base-controller` from `^8.4.1` to `^8.4.2` ([#6917](https://github.com/MetaMask/core/pull/6917))
130
112
 
131
- ### Removed
132
-
133
- - **BREAKING** A performance refactor was made around all the classes in this package ([#6654](https://github.com/MetaMask/core/pull/6654))
134
- - Remove `#handleOnAccountAdded` and `#handleOnAccountRemoved` methods in `MultichainAccountService` due to internal state being updated within the service.
135
- - Remove `getAccountContext` (and associated map) in the `MultichainAccountService` as the service no longer uses that method.
136
- - Remove the `sync` method in favor of the sole `init` method for both `MultichainAccountWallet` and `MultichainAccountGroup`.
137
-
138
113
  ## [1.6.1]
139
114
 
140
115
  ### Changed
@@ -10,20 +10,18 @@ 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 _MultichainAccountGroup_instances, _MultichainAccountGroup_id, _MultichainAccountGroup_wallet, _MultichainAccountGroup_groupIndex, _MultichainAccountGroup_providers, _MultichainAccountGroup_providerToAccounts, _MultichainAccountGroup_accountToProvider, _MultichainAccountGroup_messenger, _MultichainAccountGroup_log, _MultichainAccountGroup_initialized, _MultichainAccountGroup_clearAccountToProviderState, _MultichainAccountGroup_setState;
13
+ var _MultichainAccountGroup_id, _MultichainAccountGroup_wallet, _MultichainAccountGroup_groupIndex, _MultichainAccountGroup_providers, _MultichainAccountGroup_providerToAccounts, _MultichainAccountGroup_accountToProvider, _MultichainAccountGroup_messenger, _MultichainAccountGroup_log, _MultichainAccountGroup_initialized;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.MultichainAccountGroup = void 0;
16
16
  const account_api_1 = require("@metamask/account-api");
17
17
  const account_api_2 = require("@metamask/account-api");
18
18
  const logger_1 = require("./logger.cjs");
19
- const providers_1 = require("./providers/index.cjs");
20
19
  const utils_1 = require("./utils.cjs");
21
20
  /**
22
21
  * A multichain account group that holds multiple accounts.
23
22
  */
24
23
  class MultichainAccountGroup {
25
24
  constructor({ groupIndex, wallet, providers, messenger, }) {
26
- _MultichainAccountGroup_instances.add(this);
27
25
  _MultichainAccountGroup_id.set(this, void 0);
28
26
  _MultichainAccountGroup_wallet.set(this, void 0);
29
27
  _MultichainAccountGroup_groupIndex.set(this, void 0);
@@ -32,6 +30,7 @@ class MultichainAccountGroup {
32
30
  _MultichainAccountGroup_accountToProvider.set(this, void 0);
33
31
  _MultichainAccountGroup_messenger.set(this, void 0);
34
32
  _MultichainAccountGroup_log.set(this, void 0);
33
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly
35
34
  _MultichainAccountGroup_initialized.set(this, false);
36
35
  __classPrivateFieldSet(this, _MultichainAccountGroup_id, (0, account_api_2.toMultichainAccountGroupId)(wallet.id, groupIndex), "f");
37
36
  __classPrivateFieldSet(this, _MultichainAccountGroup_groupIndex, groupIndex, "f");
@@ -41,26 +40,41 @@ class MultichainAccountGroup {
41
40
  __classPrivateFieldSet(this, _MultichainAccountGroup_providerToAccounts, new Map(), "f");
42
41
  __classPrivateFieldSet(this, _MultichainAccountGroup_accountToProvider, new Map(), "f");
43
42
  __classPrivateFieldSet(this, _MultichainAccountGroup_log, (0, logger_1.createModuleLogger)(logger_1.projectLogger, `[${__classPrivateFieldGet(this, _MultichainAccountGroup_id, "f")}]`), "f");
43
+ this.sync();
44
+ __classPrivateFieldSet(this, _MultichainAccountGroup_initialized, true, "f");
44
45
  }
45
46
  /**
46
- * Initialize the multichain account group and construct the internal representation of accounts.
47
- *
48
- * @param groupState - The group state.
49
- */
50
- init(groupState) {
51
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Initializing group state...');
52
- __classPrivateFieldGet(this, _MultichainAccountGroup_instances, "m", _MultichainAccountGroup_setState).call(this, groupState);
53
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Finished initializing group state...');
54
- }
55
- /**
56
- * Update the group state.
47
+ * Force multichain account synchronization.
57
48
  *
58
- * @param groupState - The group state.
49
+ * This can be used if account providers got new accounts that the multichain
50
+ * account doesn't know about.
59
51
  */
60
- update(groupState) {
61
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Updating group state...');
62
- __classPrivateFieldGet(this, _MultichainAccountGroup_instances, "m", _MultichainAccountGroup_setState).call(this, groupState);
63
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Finished updating group state...');
52
+ sync() {
53
+ __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Synchronizing with account providers...');
54
+ // Clear reverse mapping and re-construct it entirely based on the refreshed
55
+ // list of accounts from each providers.
56
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
57
+ for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
58
+ // Filter account only for that index.
59
+ const accounts = [];
60
+ for (const account of provider.getAccounts()) {
61
+ if (account.options.entropy.id === this.wallet.entropySource &&
62
+ account.options.entropy.groupIndex === this.groupIndex) {
63
+ // We only use IDs to always fetch the latest version of accounts.
64
+ accounts.push(account.id);
65
+ }
66
+ }
67
+ __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
68
+ // Reverse-mapping for fast indexing.
69
+ for (const id of accounts) {
70
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(id, provider);
71
+ }
72
+ }
73
+ // Emit update event when group is synced (only if initialized)
74
+ if (__classPrivateFieldGet(this, _MultichainAccountGroup_initialized, "f")) {
75
+ __classPrivateFieldGet(this, _MultichainAccountGroup_messenger, "f").publish('MultichainAccountService:multichainAccountGroupUpdated', this);
76
+ }
77
+ __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Synchronized');
64
78
  }
65
79
  /**
66
80
  * Gets the multichain account group ID.
@@ -123,14 +137,6 @@ class MultichainAccountGroup {
123
137
  }
124
138
  return allAccounts;
125
139
  }
126
- /**
127
- * Gets the account IDs for this multichain account.
128
- *
129
- * @returns The account IDs.
130
- */
131
- getAccountIds() {
132
- return [...__classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").keys()];
133
- }
134
140
  /**
135
141
  * Gets the account for a given account ID.
136
142
  *
@@ -172,26 +178,19 @@ class MultichainAccountGroup {
172
178
  */
173
179
  async alignAccounts() {
174
180
  __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Aligning accounts...');
175
- __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").clear();
176
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
177
181
  const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f").map(async (provider) => {
178
182
  try {
179
- const accounts = await provider.alignAccounts({
180
- entropySource: this.wallet.entropySource,
181
- groupIndex: this.groupIndex,
182
- });
183
- const isDisabled = (0, providers_1.isAccountProviderWrapper)(provider) && provider.isDisabled();
184
- if (isDisabled) {
185
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, `Account provider "${provider.getName()}" is disabled, skipping alignment...`);
186
- }
187
- else if (accounts.length > 0) {
183
+ const accounts = __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").get(provider);
184
+ if (!accounts || accounts.length === 0) {
188
185
  __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, `Found missing accounts for account provider "${provider.getName()}", creating them now...`);
189
- __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
190
- for (const accountId of accounts) {
191
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(accountId, provider);
192
- }
186
+ const created = await provider.createAccounts({
187
+ entropySource: this.wallet.entropySource,
188
+ groupIndex: this.groupIndex,
189
+ });
190
+ __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, `Created ${created.length} accounts`);
191
+ return created;
193
192
  }
194
- return accounts;
193
+ return Promise.resolve();
195
194
  }
196
195
  catch (error) {
197
196
  // istanbul ignore next
@@ -204,23 +203,8 @@ class MultichainAccountGroup {
204
203
  throw error;
205
204
  }
206
205
  }));
207
- let failureMessage = '';
208
- let failureCount = 0;
209
- const groupState = results.reduce((state, result, idx) => {
210
- if (result.status === 'fulfilled' && result.value.length) {
211
- state[__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")[idx].getName()] = result.value;
212
- }
213
- else if (result.status === 'rejected') {
214
- failureCount += 1;
215
- failureMessage += `\n- ${__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")[idx].getName()}: ${result.reason.message}`;
216
- }
217
- return state;
218
- }, {});
219
- // Update group state
220
- this.update(groupState);
221
- if (failureCount > 0) {
222
- const hasMultipleFailures = failureCount > 1;
223
- const message = `Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing. ${hasMultipleFailures ? 'Providers' : 'Provider'} threw the following ${hasMultipleFailures ? 'errors' : 'error'}:${failureMessage}`;
206
+ if (results.some((result) => result.status === 'rejected')) {
207
+ const message = `Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing`;
224
208
  __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, `${logger_1.WARNING_PREFIX} ${message}`);
225
209
  console.warn(message);
226
210
  }
@@ -228,28 +212,5 @@ class MultichainAccountGroup {
228
212
  }
229
213
  }
230
214
  exports.MultichainAccountGroup = MultichainAccountGroup;
231
- _MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_groupIndex = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap(), _MultichainAccountGroup_messenger = new WeakMap(), _MultichainAccountGroup_log = new WeakMap(), _MultichainAccountGroup_initialized = new WeakMap(), _MultichainAccountGroup_instances = new WeakSet(), _MultichainAccountGroup_clearAccountToProviderState = function _MultichainAccountGroup_clearAccountToProviderState(provider) {
232
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").forEach((accountProvider, id) => {
233
- if (accountProvider === provider) {
234
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").delete(id);
235
- }
236
- });
237
- }, _MultichainAccountGroup_setState = function _MultichainAccountGroup_setState(groupState) {
238
- for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
239
- const accountIds = groupState[provider.getName()];
240
- if (accountIds) {
241
- __classPrivateFieldGet(this, _MultichainAccountGroup_instances, "m", _MultichainAccountGroup_clearAccountToProviderState).call(this, provider);
242
- __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accountIds);
243
- for (const accountId of accountIds) {
244
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(accountId, provider);
245
- }
246
- }
247
- }
248
- if (__classPrivateFieldGet(this, _MultichainAccountGroup_initialized, "f")) {
249
- __classPrivateFieldGet(this, _MultichainAccountGroup_messenger, "f").publish('MultichainAccountService:multichainAccountGroupUpdated', this);
250
- }
251
- else {
252
- __classPrivateFieldSet(this, _MultichainAccountGroup_initialized, true, "f");
253
- }
254
- };
215
+ _MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_groupIndex = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap(), _MultichainAccountGroup_messenger = new WeakMap(), _MultichainAccountGroup_log = new WeakMap(), _MultichainAccountGroup_initialized = new WeakMap();
255
216
  //# sourceMappingURL=MultichainAccountGroup.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountGroup.cjs","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountGroupType, select, selectOne } from '@metamask/account-api';\nimport { toMultichainAccountGroupId } from '@metamask/account-api';\nimport type {\n MultichainAccountGroupId,\n MultichainAccountGroup as MultichainAccountGroupDefinition,\n} from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { AccountSelector } from '@metamask/account-api';\nimport type { KeyringAccount } from '@metamask/keyring-api';\n\nimport type { Logger } from './logger';\nimport {\n projectLogger as log,\n createModuleLogger,\n WARNING_PREFIX,\n} from './logger';\nimport type { ServiceState, StateKeys } from './MultichainAccountService';\nimport type { MultichainAccountWallet } from './MultichainAccountWallet';\nimport type { Bip44AccountProvider } from './providers';\nimport { isAccountProviderWrapper } from './providers';\nimport type { MultichainAccountServiceMessenger } from './types';\nimport { createSentryError } from './utils';\n\nexport type GroupState =\n ServiceState[StateKeys['entropySource']][StateKeys['groupIndex']];\n\n/**\n * A multichain account group that holds multiple accounts.\n */\nexport class MultichainAccountGroup<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountGroupDefinition<Account>\n{\n readonly #id: MultichainAccountGroupId;\n\n readonly #wallet: MultichainAccountWallet<Account>;\n\n readonly #groupIndex: number;\n\n readonly #providers: Bip44AccountProvider<Account>[];\n\n readonly #providerToAccounts: Map<\n Bip44AccountProvider<Account>,\n Account['id'][]\n >;\n\n readonly #accountToProvider: Map<\n Account['id'],\n Bip44AccountProvider<Account>\n >;\n\n readonly #messenger: MultichainAccountServiceMessenger;\n\n readonly #log: Logger;\n\n #initialized = false;\n\n constructor({\n groupIndex,\n wallet,\n providers,\n messenger,\n }: {\n groupIndex: number;\n wallet: MultichainAccountWallet<Account>;\n providers: Bip44AccountProvider<Account>[];\n messenger: MultichainAccountServiceMessenger;\n }) {\n this.#id = toMultichainAccountGroupId(wallet.id, groupIndex);\n this.#groupIndex = groupIndex;\n this.#wallet = wallet;\n this.#providers = providers;\n this.#messenger = messenger;\n this.#providerToAccounts = new Map();\n this.#accountToProvider = new Map();\n\n this.#log = createModuleLogger(log, `[${this.#id}]`);\n }\n\n /**\n * Clear the account to provider state for a given provider.\n *\n * @param provider - The provider to clear the account to provider state for.\n */\n #clearAccountToProviderState(provider: Bip44AccountProvider<Account>): void {\n this.#accountToProvider.forEach((accountProvider, id) => {\n if (accountProvider === provider) {\n this.#accountToProvider.delete(id);\n }\n });\n }\n\n /**\n * Update the internal representation of accounts with the given group state.\n *\n * @param groupState - The group state.\n */\n #setState(groupState: GroupState): void {\n for (const provider of this.#providers) {\n const accountIds = groupState[provider.getName()];\n\n if (accountIds) {\n this.#clearAccountToProviderState(provider);\n this.#providerToAccounts.set(provider, accountIds);\n\n for (const accountId of accountIds) {\n this.#accountToProvider.set(accountId, provider);\n }\n }\n }\n\n if (this.#initialized) {\n this.#messenger.publish(\n 'MultichainAccountService:multichainAccountGroupUpdated',\n this,\n );\n } else {\n this.#initialized = true;\n }\n }\n\n /**\n * Initialize the multichain account group and construct the internal representation of accounts.\n *\n * @param groupState - The group state.\n */\n init(groupState: GroupState): void {\n this.#log('Initializing group state...');\n this.#setState(groupState);\n this.#log('Finished initializing group state...');\n }\n\n /**\n * Update the group state.\n *\n * @param groupState - The group state.\n */\n update(groupState: GroupState): void {\n this.#log('Updating group state...');\n this.#setState(groupState);\n this.#log('Finished updating group state...');\n }\n\n /**\n * Gets the multichain account group ID.\n *\n * @returns The multichain account group ID.\n */\n get id(): MultichainAccountGroupId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account group type.\n *\n * @returns The multichain account type.\n */\n get type(): AccountGroupType.MultichainAccount {\n return AccountGroupType.MultichainAccount;\n }\n\n /**\n * Gets the multichain account's wallet reference (parent).\n *\n * @returns The multichain account's wallet.\n */\n get wallet(): MultichainAccountWallet<Account> {\n return this.#wallet;\n }\n\n /**\n * Gets the multichain account group index.\n *\n * @returns The multichain account group index.\n */\n get groupIndex(): number {\n return this.#groupIndex;\n }\n\n /**\n * Checks if there's any underlying accounts for this multichain accounts.\n *\n * @returns True if there's any underlying accounts, false otherwise.\n */\n hasAccounts(): boolean {\n // If there's anything in the reverse-map, it means we have some accounts.\n return this.#accountToProvider.size > 0;\n }\n\n /**\n * Gets the accounts for this multichain account.\n *\n * @returns The accounts.\n */\n getAccounts(): Account[] {\n const allAccounts: Account[] = [];\n\n for (const [provider, accounts] of this.#providerToAccounts.entries()) {\n for (const id of accounts) {\n const account = provider.getAccount(id);\n\n if (account) {\n // If for some reason we cannot get this account from the provider, it\n // might means it has been deleted or something, so we just filter it\n // out.\n allAccounts.push(account);\n }\n }\n }\n\n return allAccounts;\n }\n\n /**\n * Gets the account IDs for this multichain account.\n *\n * @returns The account IDs.\n */\n getAccountIds(): Account['id'][] {\n return [...this.#accountToProvider.keys()];\n }\n\n /**\n * Gets the account for a given account ID.\n *\n * @param id - Account ID.\n * @returns The account or undefined if not found.\n */\n getAccount(id: Account['id']): Account | undefined {\n const provider = this.#accountToProvider.get(id);\n\n // If there's nothing in the map, it means we tried to get an account\n // that does not belong to this multichain account.\n if (!provider) {\n return undefined;\n }\n\n return provider.getAccount(id);\n }\n\n /**\n * Query an account matching the selector.\n *\n * @param selector - Query selector.\n * @returns The account matching the selector or undefined if not matching.\n * @throws If multiple accounts match the selector.\n */\n get(selector: AccountSelector<Account>): Account | undefined {\n return selectOne(this.getAccounts(), selector);\n }\n\n /**\n * Query accounts matching the selector.\n *\n * @param selector - Query selector.\n * @returns The accounts matching the selector.\n */\n select(selector: AccountSelector<Account>): Account[] {\n return select(this.getAccounts(), selector);\n }\n\n /**\n * Align the multichain account group.\n *\n * This will create accounts for providers that don't have any accounts yet.\n */\n async alignAccounts(): Promise<void> {\n this.#log('Aligning accounts...');\n\n this.#providerToAccounts.clear();\n this.#accountToProvider.clear();\n\n const results = await Promise.allSettled(\n this.#providers.map(async (provider) => {\n try {\n const accounts = await provider.alignAccounts({\n entropySource: this.wallet.entropySource,\n groupIndex: this.groupIndex,\n });\n\n const isDisabled =\n isAccountProviderWrapper(provider) && provider.isDisabled();\n\n if (isDisabled) {\n this.#log(\n `Account provider \"${provider.getName()}\" is disabled, skipping alignment...`,\n );\n } else if (accounts.length > 0) {\n this.#log(\n `Found missing accounts for account provider \"${provider.getName()}\", creating them now...`,\n );\n this.#providerToAccounts.set(provider, accounts);\n for (const accountId of accounts) {\n this.#accountToProvider.set(accountId, provider);\n }\n }\n\n return accounts;\n } catch (error) {\n // istanbul ignore next\n this.#log(\n `${WARNING_PREFIX} ${error instanceof Error ? error.message : String(error)}`,\n );\n const sentryError = createSentryError(\n `Unable to align accounts with provider \"${provider.getName()}\"`,\n error as Error,\n {\n groupIndex: this.groupIndex,\n provider: provider.getName(),\n },\n );\n this.#messenger.captureException?.(sentryError);\n throw error;\n }\n }),\n );\n\n let failureMessage = '';\n let failureCount = 0;\n const groupState = results.reduce<GroupState>((state, result, idx) => {\n if (result.status === 'fulfilled' && result.value.length) {\n state[this.#providers[idx].getName()] = result.value;\n } else if (result.status === 'rejected') {\n failureCount += 1;\n failureMessage += `\\n- ${this.#providers[idx].getName()}: ${result.reason.message}`;\n }\n return state;\n }, {});\n\n // Update group state\n this.update(groupState);\n\n if (failureCount > 0) {\n const hasMultipleFailures = failureCount > 1;\n const message = `Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing. ${hasMultipleFailures ? 'Providers' : 'Provider'} threw the following ${hasMultipleFailures ? 'errors' : 'error'}:${failureMessage}`;\n\n this.#log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n }\n\n this.#log('Aligned');\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainAccountGroup.cjs","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uDAA4E;AAC5E,uDAAmE;AAUnE,yCAIkB;AAIlB,uCAA4C;AAE5C;;GAEG;AACH,MAAa,sBAAsB;IA6BjC,YAAY,EACV,UAAU,EACV,MAAM,EACN,SAAS,EACT,SAAS,GAMV;QAnCQ,6CAA8B;QAE9B,iDAA0C;QAE1C,qDAAoB;QAEpB,oDAA4C;QAE5C,6DAGP;QAEO,4DAGP;QAEO,oDAA8C;QAE9C,8CAAa;QAEtB,8DAA8D;QAC9D,8CAAe,KAAK,EAAC;QAanB,uBAAA,IAAI,8BAAO,IAAA,wCAA0B,EAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,MAAA,CAAC;QAC7D,uBAAA,IAAI,sCAAe,UAAU,MAAA,CAAC;QAC9B,uBAAA,IAAI,kCAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,qCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,qCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,8CAAuB,IAAI,GAAG,EAAE,MAAA,CAAC;QACrC,uBAAA,IAAI,6CAAsB,IAAI,GAAG,EAAE,MAAA,CAAC;QAEpC,uBAAA,IAAI,+BAAQ,IAAA,2BAAkB,EAAC,sBAAG,EAAE,IAAI,uBAAA,IAAI,kCAAI,GAAG,CAAC,MAAA,CAAC;QAErD,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,uBAAA,IAAI,uCAAgB,IAAI,MAAA,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,IAAI;QACF,uBAAA,IAAI,mCAAK,MAAT,IAAI,EAAM,yCAAyC,CAAC,CAAC;QACrD,4EAA4E;QAC5E,wCAAwC;QACxC,uBAAA,IAAI,iDAAmB,CAAC,KAAK,EAAE,CAAC;QAEhC,KAAK,MAAM,QAAQ,IAAI,uBAAA,IAAI,yCAAW,EAAE,CAAC;YACvC,sCAAsC;YACtC,MAAM,QAAQ,GAAG,EAAE,CAAC;YACpB,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC7C,IACE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,aAAa;oBACxD,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,EACtD,CAAC;oBACD,kEAAkE;oBAClE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;YACD,uBAAA,IAAI,kDAAoB,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAEjD,qCAAqC;YACrC,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC1B,uBAAA,IAAI,iDAAmB,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,+DAA+D;QAC/D,IAAI,uBAAA,IAAI,2CAAa,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAW,CAAC,OAAO,CACrB,wDAAwD,EACxD,IAAI,CACL,CAAC;QACJ,CAAC;QAED,uBAAA,IAAI,mCAAK,MAAT,IAAI,EAAM,cAAc,CAAC,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,IAAI,EAAE;QACJ,OAAO,uBAAA,IAAI,kCAAI,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACH,IAAI,IAAI;QACN,OAAO,8BAAgB,CAAC,iBAAiB,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,IAAI,MAAM;QACR,OAAO,uBAAA,IAAI,sCAAQ,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACH,IAAI,UAAU;QACZ,OAAO,uBAAA,IAAI,0CAAY,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,0EAA0E;QAC1E,OAAO,uBAAA,IAAI,iDAAmB,CAAC,IAAI,GAAG,CAAC,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,MAAM,WAAW,GAAc,EAAE,CAAC;QAElC,KAAK,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,uBAAA,IAAI,kDAAoB,CAAC,OAAO,EAAE,EAAE,CAAC;YACtE,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBAExC,IAAI,OAAO,EAAE,CAAC;oBACZ,sEAAsE;oBACtE,qEAAqE;oBACrE,OAAO;oBACP,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,EAAiB;QAC1B,MAAM,QAAQ,GAAG,uBAAA,IAAI,iDAAmB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEjD,qEAAqE;QACrE,mDAAmD;QACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;OAMG;IACH,GAAG,CAAC,QAAkC;QACpC,OAAO,IAAA,uBAAS,EAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAkC;QACvC,OAAO,IAAA,oBAAM,EAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAa;QACjB,uBAAA,IAAI,mCAAK,MAAT,IAAI,EAAM,sBAAsB,CAAC,CAAC;QAElC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,uBAAA,IAAI,yCAAW,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;YACrC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,uBAAA,IAAI,kDAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACxD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvC,uBAAA,IAAI,mCAAK,MAAT,IAAI,EACF,gDAAgD,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAC5F,CAAC;oBACF,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC;wBAC5C,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa;wBACxC,UAAU,EAAE,IAAI,CAAC,UAAU;qBAC5B,CAAC,CAAC;oBACH,uBAAA,IAAI,mCAAK,MAAT,IAAI,EAAM,WAAW,OAAO,CAAC,MAAM,WAAW,CAAC,CAAC;oBAEhD,OAAO,OAAO,CAAC;gBACjB,CAAC;gBACD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,uBAAuB;gBACvB,uBAAA,IAAI,mCAAK,MAAT,IAAI,EACF,GAAG,uBAAc,IAAI,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC9E,CAAC;gBACF,MAAM,WAAW,GAAG,IAAA,yBAAiB,EACnC,2CAA2C,QAAQ,CAAC,OAAO,EAAE,GAAG,EAChE,KAAc,EACd;oBACE,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAAE;iBAC7B,CACF,CAAC;gBACF,uBAAA,IAAI,yCAAW,CAAC,gBAAgB,EAAE,CAAC,WAAW,CAAC,CAAC;gBAChD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CACH,CAAC;QAEF,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,EAAE,CAAC;YAC3D,MAAM,OAAO,GAAG,kEAAkE,IAAI,CAAC,MAAM,CAAC,aAAa,qBAAqB,IAAI,CAAC,UAAU,kCAAkC,CAAC;YAElL,uBAAA,IAAI,mCAAK,MAAT,IAAI,EAAM,GAAG,uBAAc,IAAI,OAAO,EAAE,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QAED,uBAAA,IAAI,mCAAK,MAAT,IAAI,EAAM,SAAS,CAAC,CAAC;IACvB,CAAC;CACF;AAlQD,wDAkQC","sourcesContent":["import { AccountGroupType, select, selectOne } from '@metamask/account-api';\nimport { toMultichainAccountGroupId } from '@metamask/account-api';\nimport type {\n MultichainAccountGroupId,\n MultichainAccountGroup as MultichainAccountGroupDefinition,\n} from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { AccountSelector } from '@metamask/account-api';\nimport type { KeyringAccount } from '@metamask/keyring-api';\n\nimport type { Logger } from './logger';\nimport {\n projectLogger as log,\n createModuleLogger,\n WARNING_PREFIX,\n} from './logger';\nimport type { MultichainAccountWallet } from './MultichainAccountWallet';\nimport type { Bip44AccountProvider } from './providers';\nimport type { MultichainAccountServiceMessenger } from './types';\nimport { createSentryError } from './utils';\n\n/**\n * A multichain account group that holds multiple accounts.\n */\nexport class MultichainAccountGroup<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountGroupDefinition<Account>\n{\n readonly #id: MultichainAccountGroupId;\n\n readonly #wallet: MultichainAccountWallet<Account>;\n\n readonly #groupIndex: number;\n\n readonly #providers: Bip44AccountProvider<Account>[];\n\n readonly #providerToAccounts: Map<\n Bip44AccountProvider<Account>,\n Account['id'][]\n >;\n\n readonly #accountToProvider: Map<\n Account['id'],\n Bip44AccountProvider<Account>\n >;\n\n readonly #messenger: MultichainAccountServiceMessenger;\n\n readonly #log: Logger;\n\n // eslint-disable-next-line @typescript-eslint/prefer-readonly\n #initialized = false;\n\n constructor({\n groupIndex,\n wallet,\n providers,\n messenger,\n }: {\n groupIndex: number;\n wallet: MultichainAccountWallet<Account>;\n providers: Bip44AccountProvider<Account>[];\n messenger: MultichainAccountServiceMessenger;\n }) {\n this.#id = toMultichainAccountGroupId(wallet.id, groupIndex);\n this.#groupIndex = groupIndex;\n this.#wallet = wallet;\n this.#providers = providers;\n this.#messenger = messenger;\n this.#providerToAccounts = new Map();\n this.#accountToProvider = new Map();\n\n this.#log = createModuleLogger(log, `[${this.#id}]`);\n\n this.sync();\n this.#initialized = true;\n }\n\n /**\n * Force multichain account synchronization.\n *\n * This can be used if account providers got new accounts that the multichain\n * account doesn't know about.\n */\n sync(): void {\n this.#log('Synchronizing with account providers...');\n // Clear reverse mapping and re-construct it entirely based on the refreshed\n // list of accounts from each providers.\n this.#accountToProvider.clear();\n\n for (const provider of this.#providers) {\n // Filter account only for that index.\n const accounts = [];\n for (const account of provider.getAccounts()) {\n if (\n account.options.entropy.id === this.wallet.entropySource &&\n account.options.entropy.groupIndex === this.groupIndex\n ) {\n // We only use IDs to always fetch the latest version of accounts.\n accounts.push(account.id);\n }\n }\n this.#providerToAccounts.set(provider, accounts);\n\n // Reverse-mapping for fast indexing.\n for (const id of accounts) {\n this.#accountToProvider.set(id, provider);\n }\n }\n\n // Emit update event when group is synced (only if initialized)\n if (this.#initialized) {\n this.#messenger.publish(\n 'MultichainAccountService:multichainAccountGroupUpdated',\n this,\n );\n }\n\n this.#log('Synchronized');\n }\n\n /**\n * Gets the multichain account group ID.\n *\n * @returns The multichain account group ID.\n */\n get id(): MultichainAccountGroupId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account group type.\n *\n * @returns The multichain account type.\n */\n get type(): AccountGroupType.MultichainAccount {\n return AccountGroupType.MultichainAccount;\n }\n\n /**\n * Gets the multichain account's wallet reference (parent).\n *\n * @returns The multichain account's wallet.\n */\n get wallet(): MultichainAccountWallet<Account> {\n return this.#wallet;\n }\n\n /**\n * Gets the multichain account group index.\n *\n * @returns The multichain account group index.\n */\n get groupIndex(): number {\n return this.#groupIndex;\n }\n\n /**\n * Checks if there's any underlying accounts for this multichain accounts.\n *\n * @returns True if there's any underlying accounts, false otherwise.\n */\n hasAccounts(): boolean {\n // If there's anything in the reverse-map, it means we have some accounts.\n return this.#accountToProvider.size > 0;\n }\n\n /**\n * Gets the accounts for this multichain account.\n *\n * @returns The accounts.\n */\n getAccounts(): Account[] {\n const allAccounts: Account[] = [];\n\n for (const [provider, accounts] of this.#providerToAccounts.entries()) {\n for (const id of accounts) {\n const account = provider.getAccount(id);\n\n if (account) {\n // If for some reason we cannot get this account from the provider, it\n // might means it has been deleted or something, so we just filter it\n // out.\n allAccounts.push(account);\n }\n }\n }\n\n return allAccounts;\n }\n\n /**\n * Gets the account for a given account ID.\n *\n * @param id - Account ID.\n * @returns The account or undefined if not found.\n */\n getAccount(id: Account['id']): Account | undefined {\n const provider = this.#accountToProvider.get(id);\n\n // If there's nothing in the map, it means we tried to get an account\n // that does not belong to this multichain account.\n if (!provider) {\n return undefined;\n }\n return provider.getAccount(id);\n }\n\n /**\n * Query an account matching the selector.\n *\n * @param selector - Query selector.\n * @returns The account matching the selector or undefined if not matching.\n * @throws If multiple accounts match the selector.\n */\n get(selector: AccountSelector<Account>): Account | undefined {\n return selectOne(this.getAccounts(), selector);\n }\n\n /**\n * Query accounts matching the selector.\n *\n * @param selector - Query selector.\n * @returns The accounts matching the selector.\n */\n select(selector: AccountSelector<Account>): Account[] {\n return select(this.getAccounts(), selector);\n }\n\n /**\n * Align the multichain account group.\n *\n * This will create accounts for providers that don't have any accounts yet.\n */\n async alignAccounts(): Promise<void> {\n this.#log('Aligning accounts...');\n\n const results = await Promise.allSettled(\n this.#providers.map(async (provider) => {\n try {\n const accounts = this.#providerToAccounts.get(provider);\n if (!accounts || accounts.length === 0) {\n this.#log(\n `Found missing accounts for account provider \"${provider.getName()}\", creating them now...`,\n );\n const created = await provider.createAccounts({\n entropySource: this.wallet.entropySource,\n groupIndex: this.groupIndex,\n });\n this.#log(`Created ${created.length} accounts`);\n\n return created;\n }\n return Promise.resolve();\n } catch (error) {\n // istanbul ignore next\n this.#log(\n `${WARNING_PREFIX} ${error instanceof Error ? error.message : String(error)}`,\n );\n const sentryError = createSentryError(\n `Unable to align accounts with provider \"${provider.getName()}\"`,\n error as Error,\n {\n groupIndex: this.groupIndex,\n provider: provider.getName(),\n },\n );\n this.#messenger.captureException?.(sentryError);\n throw error;\n }\n }),\n );\n\n if (results.some((result) => result.status === 'rejected')) {\n const message = `Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing`;\n\n this.#log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n }\n\n this.#log('Aligned');\n }\n}\n"]}
@@ -3,11 +3,9 @@ import type { MultichainAccountGroupId, MultichainAccountGroup as MultichainAcco
3
3
  import type { Bip44Account } from "@metamask/account-api";
4
4
  import type { AccountSelector } from "@metamask/account-api";
5
5
  import type { KeyringAccount } from "@metamask/keyring-api";
6
- import type { ServiceState, StateKeys } from "./MultichainAccountService.cjs";
7
6
  import type { MultichainAccountWallet } from "./MultichainAccountWallet.cjs";
8
7
  import type { Bip44AccountProvider } from "./providers/index.cjs";
9
8
  import type { MultichainAccountServiceMessenger } from "./types.cjs";
10
- export type GroupState = ServiceState[StateKeys['entropySource']][StateKeys['groupIndex']];
11
9
  /**
12
10
  * A multichain account group that holds multiple accounts.
13
11
  */
@@ -20,17 +18,12 @@ export declare class MultichainAccountGroup<Account extends Bip44Account<Keyring
20
18
  messenger: MultichainAccountServiceMessenger;
21
19
  });
22
20
  /**
23
- * Initialize the multichain account group and construct the internal representation of accounts.
21
+ * Force multichain account synchronization.
24
22
  *
25
- * @param groupState - The group state.
23
+ * This can be used if account providers got new accounts that the multichain
24
+ * account doesn't know about.
26
25
  */
27
- init(groupState: GroupState): void;
28
- /**
29
- * Update the group state.
30
- *
31
- * @param groupState - The group state.
32
- */
33
- update(groupState: GroupState): void;
26
+ sync(): void;
34
27
  /**
35
28
  * Gets the multichain account group ID.
36
29
  *
@@ -67,12 +60,6 @@ export declare class MultichainAccountGroup<Account extends Bip44Account<Keyring
67
60
  * @returns The accounts.
68
61
  */
69
62
  getAccounts(): Account[];
70
- /**
71
- * Gets the account IDs for this multichain account.
72
- *
73
- * @returns The account IDs.
74
- */
75
- getAccountIds(): Account['id'][];
76
63
  /**
77
64
  * Gets the account for a given account ID.
78
65
  *
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountGroup.d.cts","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,8BAA8B;AAE5E,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,IAAI,gCAAgC,EAC3D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAQ5D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,uCAAmC;AAC1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAAoB;AAExD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAGjE,MAAM,MAAM,UAAU,GACpB,YAAY,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;AAEpE;;GAEG;AACH,qBAAa,sBAAsB,CACjC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,gCAAgC,CAAC,OAAO,CAAC;;gBA0BxC,EACV,UAAU,EACV,MAAM,EACN,SAAS,EACT,SAAS,GACV,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,SAAS,EAAE,iCAAiC,CAAC;KAC9C;IAsDD;;;;OAIG;IACH,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAMlC;;;;OAIG;IACH,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAMpC;;;;OAIG;IACH,IAAI,EAAE,IAAI,wBAAwB,CAEjC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,gBAAgB,CAAC,iBAAiB,CAE7C;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAE7C;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAKtB;;;;OAIG;IACH,WAAW,IAAI,OAAO,EAAE;IAmBxB;;;;OAIG;IACH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE;IAIhC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,SAAS;IAYlD;;;;;;OAMG;IACH,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;IAI5D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,EAAE;IAIrD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CA4ErC"}
1
+ {"version":3,"file":"MultichainAccountGroup.d.cts","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,8BAA8B;AAE5E,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,IAAI,gCAAgC,EAC3D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAQ5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAAoB;AACxD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAGjE;;GAEG;AACH,qBAAa,sBAAsB,CACjC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,gCAAgC,CAAC,OAAO,CAAC;;gBA2BxC,EACV,UAAU,EACV,MAAM,EACN,SAAS,EACT,SAAS,GACV,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,SAAS,EAAE,iCAAiC,CAAC;KAC9C;IAeD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAqCZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,wBAAwB,CAEjC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,gBAAgB,CAAC,iBAAiB,CAE7C;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAE7C;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAKtB;;;;OAIG;IACH,WAAW,IAAI,OAAO,EAAE;IAmBxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,SAAS;IAWlD;;;;;;OAMG;IACH,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;IAI5D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,EAAE;IAIrD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAgDrC"}
@@ -3,11 +3,9 @@ import type { MultichainAccountGroupId, MultichainAccountGroup as MultichainAcco
3
3
  import type { Bip44Account } from "@metamask/account-api";
4
4
  import type { AccountSelector } from "@metamask/account-api";
5
5
  import type { KeyringAccount } from "@metamask/keyring-api";
6
- import type { ServiceState, StateKeys } from "./MultichainAccountService.mjs";
7
6
  import type { MultichainAccountWallet } from "./MultichainAccountWallet.mjs";
8
7
  import type { Bip44AccountProvider } from "./providers/index.mjs";
9
8
  import type { MultichainAccountServiceMessenger } from "./types.mjs";
10
- export type GroupState = ServiceState[StateKeys['entropySource']][StateKeys['groupIndex']];
11
9
  /**
12
10
  * A multichain account group that holds multiple accounts.
13
11
  */
@@ -20,17 +18,12 @@ export declare class MultichainAccountGroup<Account extends Bip44Account<Keyring
20
18
  messenger: MultichainAccountServiceMessenger;
21
19
  });
22
20
  /**
23
- * Initialize the multichain account group and construct the internal representation of accounts.
21
+ * Force multichain account synchronization.
24
22
  *
25
- * @param groupState - The group state.
23
+ * This can be used if account providers got new accounts that the multichain
24
+ * account doesn't know about.
26
25
  */
27
- init(groupState: GroupState): void;
28
- /**
29
- * Update the group state.
30
- *
31
- * @param groupState - The group state.
32
- */
33
- update(groupState: GroupState): void;
26
+ sync(): void;
34
27
  /**
35
28
  * Gets the multichain account group ID.
36
29
  *
@@ -67,12 +60,6 @@ export declare class MultichainAccountGroup<Account extends Bip44Account<Keyring
67
60
  * @returns The accounts.
68
61
  */
69
62
  getAccounts(): Account[];
70
- /**
71
- * Gets the account IDs for this multichain account.
72
- *
73
- * @returns The account IDs.
74
- */
75
- getAccountIds(): Account['id'][];
76
63
  /**
77
64
  * Gets the account for a given account ID.
78
65
  *
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountGroup.d.mts","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,8BAA8B;AAE5E,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,IAAI,gCAAgC,EAC3D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAQ5D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,uCAAmC;AAC1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAAoB;AAExD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAGjE,MAAM,MAAM,UAAU,GACpB,YAAY,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;AAEpE;;GAEG;AACH,qBAAa,sBAAsB,CACjC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,gCAAgC,CAAC,OAAO,CAAC;;gBA0BxC,EACV,UAAU,EACV,MAAM,EACN,SAAS,EACT,SAAS,GACV,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,SAAS,EAAE,iCAAiC,CAAC;KAC9C;IAsDD;;;;OAIG;IACH,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAMlC;;;;OAIG;IACH,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAMpC;;;;OAIG;IACH,IAAI,EAAE,IAAI,wBAAwB,CAEjC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,gBAAgB,CAAC,iBAAiB,CAE7C;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAE7C;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAKtB;;;;OAIG;IACH,WAAW,IAAI,OAAO,EAAE;IAmBxB;;;;OAIG;IACH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE;IAIhC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,SAAS;IAYlD;;;;;;OAMG;IACH,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;IAI5D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,EAAE;IAIrD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CA4ErC"}
1
+ {"version":3,"file":"MultichainAccountGroup.d.mts","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,8BAA8B;AAE5E,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,IAAI,gCAAgC,EAC3D,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAQ5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAAoB;AACxD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAGjE;;GAEG;AACH,qBAAa,sBAAsB,CACjC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,gCAAgC,CAAC,OAAO,CAAC;;gBA2BxC,EACV,UAAU,EACV,MAAM,EACN,SAAS,EACT,SAAS,GACV,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,SAAS,EAAE,iCAAiC,CAAC;KAC9C;IAeD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAqCZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,wBAAwB,CAEjC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,gBAAgB,CAAC,iBAAiB,CAE7C;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAE7C;IAED;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAKtB;;;;OAIG;IACH,WAAW,IAAI,OAAO,EAAE;IAmBxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,SAAS;IAWlD;;;;;;OAMG;IACH,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;IAI5D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,EAAE;IAIrD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAgDrC"}
@@ -9,18 +9,16 @@ 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 _MultichainAccountGroup_instances, _MultichainAccountGroup_id, _MultichainAccountGroup_wallet, _MultichainAccountGroup_groupIndex, _MultichainAccountGroup_providers, _MultichainAccountGroup_providerToAccounts, _MultichainAccountGroup_accountToProvider, _MultichainAccountGroup_messenger, _MultichainAccountGroup_log, _MultichainAccountGroup_initialized, _MultichainAccountGroup_clearAccountToProviderState, _MultichainAccountGroup_setState;
12
+ var _MultichainAccountGroup_id, _MultichainAccountGroup_wallet, _MultichainAccountGroup_groupIndex, _MultichainAccountGroup_providers, _MultichainAccountGroup_providerToAccounts, _MultichainAccountGroup_accountToProvider, _MultichainAccountGroup_messenger, _MultichainAccountGroup_log, _MultichainAccountGroup_initialized;
13
13
  import { AccountGroupType, select, selectOne } from "@metamask/account-api";
14
14
  import { toMultichainAccountGroupId } from "@metamask/account-api";
15
15
  import { projectLogger as log, createModuleLogger, WARNING_PREFIX } from "./logger.mjs";
16
- import { isAccountProviderWrapper } from "./providers/index.mjs";
17
16
  import { createSentryError } from "./utils.mjs";
18
17
  /**
19
18
  * A multichain account group that holds multiple accounts.
20
19
  */
21
20
  export class MultichainAccountGroup {
22
21
  constructor({ groupIndex, wallet, providers, messenger, }) {
23
- _MultichainAccountGroup_instances.add(this);
24
22
  _MultichainAccountGroup_id.set(this, void 0);
25
23
  _MultichainAccountGroup_wallet.set(this, void 0);
26
24
  _MultichainAccountGroup_groupIndex.set(this, void 0);
@@ -29,6 +27,7 @@ export class MultichainAccountGroup {
29
27
  _MultichainAccountGroup_accountToProvider.set(this, void 0);
30
28
  _MultichainAccountGroup_messenger.set(this, void 0);
31
29
  _MultichainAccountGroup_log.set(this, void 0);
30
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly
32
31
  _MultichainAccountGroup_initialized.set(this, false);
33
32
  __classPrivateFieldSet(this, _MultichainAccountGroup_id, toMultichainAccountGroupId(wallet.id, groupIndex), "f");
34
33
  __classPrivateFieldSet(this, _MultichainAccountGroup_groupIndex, groupIndex, "f");
@@ -38,26 +37,41 @@ export class MultichainAccountGroup {
38
37
  __classPrivateFieldSet(this, _MultichainAccountGroup_providerToAccounts, new Map(), "f");
39
38
  __classPrivateFieldSet(this, _MultichainAccountGroup_accountToProvider, new Map(), "f");
40
39
  __classPrivateFieldSet(this, _MultichainAccountGroup_log, createModuleLogger(log, `[${__classPrivateFieldGet(this, _MultichainAccountGroup_id, "f")}]`), "f");
40
+ this.sync();
41
+ __classPrivateFieldSet(this, _MultichainAccountGroup_initialized, true, "f");
41
42
  }
42
43
  /**
43
- * Initialize the multichain account group and construct the internal representation of accounts.
44
- *
45
- * @param groupState - The group state.
46
- */
47
- init(groupState) {
48
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Initializing group state...');
49
- __classPrivateFieldGet(this, _MultichainAccountGroup_instances, "m", _MultichainAccountGroup_setState).call(this, groupState);
50
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Finished initializing group state...');
51
- }
52
- /**
53
- * Update the group state.
44
+ * Force multichain account synchronization.
54
45
  *
55
- * @param groupState - The group state.
46
+ * This can be used if account providers got new accounts that the multichain
47
+ * account doesn't know about.
56
48
  */
57
- update(groupState) {
58
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Updating group state...');
59
- __classPrivateFieldGet(this, _MultichainAccountGroup_instances, "m", _MultichainAccountGroup_setState).call(this, groupState);
60
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Finished updating group state...');
49
+ sync() {
50
+ __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Synchronizing with account providers...');
51
+ // Clear reverse mapping and re-construct it entirely based on the refreshed
52
+ // list of accounts from each providers.
53
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
54
+ for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
55
+ // Filter account only for that index.
56
+ const accounts = [];
57
+ for (const account of provider.getAccounts()) {
58
+ if (account.options.entropy.id === this.wallet.entropySource &&
59
+ account.options.entropy.groupIndex === this.groupIndex) {
60
+ // We only use IDs to always fetch the latest version of accounts.
61
+ accounts.push(account.id);
62
+ }
63
+ }
64
+ __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
65
+ // Reverse-mapping for fast indexing.
66
+ for (const id of accounts) {
67
+ __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(id, provider);
68
+ }
69
+ }
70
+ // Emit update event when group is synced (only if initialized)
71
+ if (__classPrivateFieldGet(this, _MultichainAccountGroup_initialized, "f")) {
72
+ __classPrivateFieldGet(this, _MultichainAccountGroup_messenger, "f").publish('MultichainAccountService:multichainAccountGroupUpdated', this);
73
+ }
74
+ __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Synchronized');
61
75
  }
62
76
  /**
63
77
  * Gets the multichain account group ID.
@@ -120,14 +134,6 @@ export class MultichainAccountGroup {
120
134
  }
121
135
  return allAccounts;
122
136
  }
123
- /**
124
- * Gets the account IDs for this multichain account.
125
- *
126
- * @returns The account IDs.
127
- */
128
- getAccountIds() {
129
- return [...__classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").keys()];
130
- }
131
137
  /**
132
138
  * Gets the account for a given account ID.
133
139
  *
@@ -169,26 +175,19 @@ export class MultichainAccountGroup {
169
175
  */
170
176
  async alignAccounts() {
171
177
  __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Aligning accounts...');
172
- __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").clear();
173
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
174
178
  const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f").map(async (provider) => {
175
179
  try {
176
- const accounts = await provider.alignAccounts({
177
- entropySource: this.wallet.entropySource,
178
- groupIndex: this.groupIndex,
179
- });
180
- const isDisabled = isAccountProviderWrapper(provider) && provider.isDisabled();
181
- if (isDisabled) {
182
- __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, `Account provider "${provider.getName()}" is disabled, skipping alignment...`);
183
- }
184
- else if (accounts.length > 0) {
180
+ const accounts = __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").get(provider);
181
+ if (!accounts || accounts.length === 0) {
185
182
  __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, `Found missing accounts for account provider "${provider.getName()}", creating them now...`);
186
- __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
187
- for (const accountId of accounts) {
188
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(accountId, provider);
189
- }
183
+ const created = await provider.createAccounts({
184
+ entropySource: this.wallet.entropySource,
185
+ groupIndex: this.groupIndex,
186
+ });
187
+ __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, `Created ${created.length} accounts`);
188
+ return created;
190
189
  }
191
- return accounts;
190
+ return Promise.resolve();
192
191
  }
193
192
  catch (error) {
194
193
  // istanbul ignore next
@@ -201,51 +200,13 @@ export class MultichainAccountGroup {
201
200
  throw error;
202
201
  }
203
202
  }));
204
- let failureMessage = '';
205
- let failureCount = 0;
206
- const groupState = results.reduce((state, result, idx) => {
207
- if (result.status === 'fulfilled' && result.value.length) {
208
- state[__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")[idx].getName()] = result.value;
209
- }
210
- else if (result.status === 'rejected') {
211
- failureCount += 1;
212
- failureMessage += `\n- ${__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")[idx].getName()}: ${result.reason.message}`;
213
- }
214
- return state;
215
- }, {});
216
- // Update group state
217
- this.update(groupState);
218
- if (failureCount > 0) {
219
- const hasMultipleFailures = failureCount > 1;
220
- const message = `Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing. ${hasMultipleFailures ? 'Providers' : 'Provider'} threw the following ${hasMultipleFailures ? 'errors' : 'error'}:${failureMessage}`;
203
+ if (results.some((result) => result.status === 'rejected')) {
204
+ const message = `Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing`;
221
205
  __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, `${WARNING_PREFIX} ${message}`);
222
206
  console.warn(message);
223
207
  }
224
208
  __classPrivateFieldGet(this, _MultichainAccountGroup_log, "f").call(this, 'Aligned');
225
209
  }
226
210
  }
227
- _MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_groupIndex = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap(), _MultichainAccountGroup_messenger = new WeakMap(), _MultichainAccountGroup_log = new WeakMap(), _MultichainAccountGroup_initialized = new WeakMap(), _MultichainAccountGroup_instances = new WeakSet(), _MultichainAccountGroup_clearAccountToProviderState = function _MultichainAccountGroup_clearAccountToProviderState(provider) {
228
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").forEach((accountProvider, id) => {
229
- if (accountProvider === provider) {
230
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").delete(id);
231
- }
232
- });
233
- }, _MultichainAccountGroup_setState = function _MultichainAccountGroup_setState(groupState) {
234
- for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
235
- const accountIds = groupState[provider.getName()];
236
- if (accountIds) {
237
- __classPrivateFieldGet(this, _MultichainAccountGroup_instances, "m", _MultichainAccountGroup_clearAccountToProviderState).call(this, provider);
238
- __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accountIds);
239
- for (const accountId of accountIds) {
240
- __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(accountId, provider);
241
- }
242
- }
243
- }
244
- if (__classPrivateFieldGet(this, _MultichainAccountGroup_initialized, "f")) {
245
- __classPrivateFieldGet(this, _MultichainAccountGroup_messenger, "f").publish('MultichainAccountService:multichainAccountGroupUpdated', this);
246
- }
247
- else {
248
- __classPrivateFieldSet(this, _MultichainAccountGroup_initialized, true, "f");
249
- }
250
- };
211
+ _MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_groupIndex = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap(), _MultichainAccountGroup_messenger = new WeakMap(), _MultichainAccountGroup_log = new WeakMap(), _MultichainAccountGroup_initialized = new WeakMap();
251
212
  //# sourceMappingURL=MultichainAccountGroup.mjs.map