@metamask-previews/multichain-account-service 4.0.0-preview-7334bbce → 4.0.0-preview-e540d3bf

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 -21
  2. package/dist/MultichainAccountGroup.cjs +45 -84
  3. package/dist/MultichainAccountGroup.cjs.map +1 -1
  4. package/dist/MultichainAccountGroup.d.cts +5 -18
  5. package/dist/MultichainAccountGroup.d.cts.map +1 -1
  6. package/dist/MultichainAccountGroup.d.mts +5 -18
  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 -126
  11. package/dist/MultichainAccountService.cjs.map +1 -1
  12. package/dist/MultichainAccountService.d.cts +20 -36
  13. package/dist/MultichainAccountService.d.cts.map +1 -1
  14. package/dist/MultichainAccountService.d.mts +20 -36
  15. package/dist/MultichainAccountService.d.mts.map +1 -1
  16. package/dist/MultichainAccountService.mjs +114 -127
  17. package/dist/MultichainAccountService.mjs.map +1 -1
  18. package/dist/MultichainAccountWallet.cjs +123 -107
  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 +124 -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 -3
  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 -3
  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 +3 -3
  84. package/dist/types.d.cts.map +1 -1
  85. package/dist/types.d.mts +3 -3
  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 +1 -1
package/CHANGELOG.md CHANGED
@@ -7,13 +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
10
  ### Changed
18
11
 
19
12
  - Move peer dependencies for controller and service packages to direct dependencies ([#7209](https://github.com/MetaMask/core/pull/7209))
@@ -79,22 +72,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
79
72
 
80
73
  ### Changed
81
74
 
82
- - **BREAKING** A performance refactor was made around all the classes in this package ([#6654](https://github.com/MetaMask/core/pull/6654))
83
- - 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.
84
- - Additional state is generated at the entry points where it needs to be updated i.e. `createMultichainAccountGroup`, `discoverAccounts` and `alignAccounts`.
85
- - We no longer prevent group creation if some providers' `createAccounts` calls fail during group creation, only if they all fail.
86
- - 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.
87
- - The `EvmAccountProvider` no longer fetches from the `AccountController` to get an account for its ID, we deterministically get the associated account ID through `getUUIDFromAddressOfNormalAccount`.
88
- - The `EvmAccountProvider` now uses the `getAccount` method from the `AccountsController` when fetching an account after account creation as it is more efficient.
89
75
  - Bump `@metamask/base-controller` from `^8.4.1` to `^8.4.2` ([#6917](https://github.com/MetaMask/core/pull/6917))
90
76
 
91
- ### Removed
92
-
93
- - **BREAKING** A performance refactor was made around all the classes in this package ([#6654](https://github.com/MetaMask/core/pull/6654))
94
- - Remove `#handleOnAccountAdded` and `#handleOnAccountRemoved` methods in `MultichainAccountService` due to internal state being updated within the service.
95
- - Remove `getAccountContext` (and associated map) in the `MultichainAccountService` as the service no longer uses that method.
96
- - Remove the `sync` method in favor of the sole `init` method for both `MultichainAccountWallet` and `MultichainAccountGroup`.
97
-
98
77
  ## [1.6.1]
99
78
 
100
79
  ### 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((p, id) => {
233
- if (p === 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
- __classPrivateFieldGet(this, _MultichainAccountGroup_instances, "m", _MultichainAccountGroup_clearAccountToProviderState).call(this, provider);
241
- if (accountIds) {
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
- __classPrivateFieldSet(this, _MultichainAccountGroup_initialized, true, "f");
250
- }
251
- else {
252
- __classPrivateFieldGet(this, _MultichainAccountGroup_messenger, "f").publish('MultichainAccountService:multichainAccountGroupUpdated', this);
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 {\n toMultichainAccountGroupId,\n type MultichainAccountGroupId,\n type 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 {\n isAccountProviderWrapper,\n type Bip44AccountProvider,\n} 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>) {\n this.#accountToProvider.forEach((p, id) => {\n if (p === 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) {\n for (const provider of this.#providers) {\n const accountIds = groupState[provider.getName()];\n this.#clearAccountToProviderState(provider);\n\n if (accountIds) {\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.#initialized = true;\n } else {\n this.#messenger.publish(\n 'MultichainAccountService:multichainAccountGroupUpdated',\n this,\n );\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) {\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) {\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.call(\n 'ErrorReportingService:captureException',\n sentryError,\n );\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,uDAI+B;AAM/B,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,IAAI,CAClB,wCAAwC,EACxC,WAAW,CACZ,CAAC;gBACF,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;AArQD,wDAqQC","sourcesContent":["import { AccountGroupType, select, selectOne } from '@metamask/account-api';\nimport {\n toMultichainAccountGroupId,\n type MultichainAccountGroupId,\n type 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.call(\n 'ErrorReportingService:captureException',\n sentryError,\n );\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, type MultichainAccountGroup as Multichai
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
- import { type Bip44AccountProvider } from "./providers/index.cjs";
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;AAC5E,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,IAAI,gCAAgC,EAChE,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EAAE,KAAK,cAAc,EAAE,8BAA8B;AAQ5D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,uCAAmC;AAC1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AACzE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,8BAAoB;AACrB,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;IAM3B;;;;OAIG;IACH,MAAM,CAAC,UAAU,EAAE,UAAU;IAM7B;;;;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;CA+ErC"}
1
+ {"version":3,"file":"MultichainAccountGroup.d.cts","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,8BAA8B;AAC5E,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,IAAI,gCAAgC,EAChE,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EAAE,KAAK,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;CAmDrC"}
@@ -3,11 +3,9 @@ import { type MultichainAccountGroupId, type MultichainAccountGroup as Multichai
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
- import { type Bip44AccountProvider } from "./providers/index.mjs";
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;AAC5E,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,IAAI,gCAAgC,EAChE,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EAAE,KAAK,cAAc,EAAE,8BAA8B;AAQ5D,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,uCAAmC;AAC1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AACzE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,8BAAoB;AACrB,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;IAM3B;;;;OAIG;IACH,MAAM,CAAC,UAAU,EAAE,UAAU;IAM7B;;;;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;CA+ErC"}
1
+ {"version":3,"file":"MultichainAccountGroup.d.mts","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAqB,8BAA8B;AAC5E,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,IAAI,gCAAgC,EAChE,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,EAAE,KAAK,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;CAmDrC"}
@@ -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((p, id) => {
229
- if (p === 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
- __classPrivateFieldGet(this, _MultichainAccountGroup_instances, "m", _MultichainAccountGroup_clearAccountToProviderState).call(this, provider);
237
- if (accountIds) {
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
- __classPrivateFieldSet(this, _MultichainAccountGroup_initialized, true, "f");
246
- }
247
- else {
248
- __classPrivateFieldGet(this, _MultichainAccountGroup_messenger, "f").publish('MultichainAccountService:multichainAccountGroupUpdated', this);
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