@metamask-previews/multichain-account-service 1.0.0-preview-8ccfcb37 → 1.2.0-preview-a5441fae

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 (42) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/dist/MultichainAccountGroup.cjs +17 -5
  3. package/dist/MultichainAccountGroup.cjs.map +1 -1
  4. package/dist/MultichainAccountGroup.d.cts.map +1 -1
  5. package/dist/MultichainAccountGroup.d.mts.map +1 -1
  6. package/dist/MultichainAccountGroup.mjs +17 -5
  7. package/dist/MultichainAccountGroup.mjs.map +1 -1
  8. package/dist/MultichainAccountService.cjs +14 -0
  9. package/dist/MultichainAccountService.cjs.map +1 -1
  10. package/dist/MultichainAccountService.d.cts.map +1 -1
  11. package/dist/MultichainAccountService.d.mts.map +1 -1
  12. package/dist/MultichainAccountService.mjs +14 -0
  13. package/dist/MultichainAccountService.mjs.map +1 -1
  14. package/dist/MultichainAccountWallet.cjs +24 -12
  15. package/dist/MultichainAccountWallet.cjs.map +1 -1
  16. package/dist/MultichainAccountWallet.d.cts.map +1 -1
  17. package/dist/MultichainAccountWallet.d.mts.map +1 -1
  18. package/dist/MultichainAccountWallet.mjs +24 -12
  19. package/dist/MultichainAccountWallet.mjs.map +1 -1
  20. package/dist/logger.cjs +8 -0
  21. package/dist/logger.cjs.map +1 -0
  22. package/dist/logger.d.cts +7 -0
  23. package/dist/logger.d.cts.map +1 -0
  24. package/dist/logger.d.mts +7 -0
  25. package/dist/logger.d.mts.map +1 -0
  26. package/dist/logger.mjs +5 -0
  27. package/dist/logger.mjs.map +1 -0
  28. package/dist/providers/SolAccountProvider.cjs +4 -1
  29. package/dist/providers/SolAccountProvider.cjs.map +1 -1
  30. package/dist/providers/SolAccountProvider.d.cts +3 -0
  31. package/dist/providers/SolAccountProvider.d.cts.map +1 -1
  32. package/dist/providers/SolAccountProvider.d.mts +3 -0
  33. package/dist/providers/SolAccountProvider.d.mts.map +1 -1
  34. package/dist/providers/SolAccountProvider.mjs +4 -1
  35. package/dist/providers/SolAccountProvider.mjs.map +1 -1
  36. package/dist/tests/providers.cjs +1 -0
  37. package/dist/tests/providers.cjs.map +1 -1
  38. package/dist/tests/providers.d.cts.map +1 -1
  39. package/dist/tests/providers.d.mts.map +1 -1
  40. package/dist/tests/providers.mjs +1 -0
  41. package/dist/tests/providers.mjs.map +1 -1
  42. package/package.json +2 -2
@@ -14,6 +14,7 @@ import { isBip44Account, toMultichainAccountWalletId } from "@metamask/account-a
14
14
  import { mnemonicPhraseToBytes } from "@metamask/key-tree";
15
15
  import { KeyringTypes } from "@metamask/keyring-controller";
16
16
  import { areUint8ArraysEqual } from "@metamask/utils";
17
+ import { projectLogger as log } from "./logger.mjs";
17
18
  import { MultichainAccountWallet } from "./MultichainAccountWallet.mjs";
18
19
  import { AccountProviderWrapper, isAccountProviderWrapper } from "./providers/AccountProviderWrapper.mjs";
19
20
  import { EvmAccountProvider } from "./providers/EvmAccountProvider.mjs";
@@ -71,6 +72,7 @@ export class MultichainAccountService {
71
72
  * multichain accounts and wallets.
72
73
  */
73
74
  init() {
75
+ log('Initializing...');
74
76
  __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").clear();
75
77
  __classPrivateFieldGet(this, _MultichainAccountService_accountIdToContext, "f").clear();
76
78
  // Create initial wallets.
@@ -79,6 +81,7 @@ export class MultichainAccountService {
79
81
  if (keyring.type === KeyringTypes.hd) {
80
82
  // Only HD keyrings have an entropy source/SRP.
81
83
  const entropySource = keyring.metadata.id;
84
+ log(`Adding new wallet for entropy: "${entropySource}"`);
82
85
  // This will automatically "associate" all multichain accounts for that wallet
83
86
  // (based on the accounts owned by each account providers).
84
87
  const wallet = new MultichainAccountWallet({
@@ -98,6 +101,7 @@ export class MultichainAccountService {
98
101
  }
99
102
  }
100
103
  }
104
+ log('Initialized');
101
105
  }
102
106
  /**
103
107
  * Gets the account's context which contains its multichain wallet and
@@ -151,6 +155,7 @@ export class MultichainAccountService {
151
155
  if (alreadyHasImportedSrp) {
152
156
  throw new Error('This Secret Recovery Phrase has already been imported.');
153
157
  }
158
+ log(`Creating new wallet...`);
154
159
  const result = await __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").call('KeyringController:addNewKeyring', KeyringTypes.hd, { mnemonic });
155
160
  const wallet = new MultichainAccountWallet({
156
161
  providers: __classPrivateFieldGet(this, _MultichainAccountService_providers, "f"),
@@ -158,6 +163,7 @@ export class MultichainAccountService {
158
163
  messenger: __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f"),
159
164
  });
160
165
  __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").set(wallet.id, wallet);
166
+ log(`Wallet created: [${wallet.id}]`);
161
167
  return wallet;
162
168
  }
163
169
  /**
@@ -218,9 +224,11 @@ export class MultichainAccountService {
218
224
  * @param enabled - Whether basic functionality is enabled.
219
225
  */
220
226
  async setBasicFunctionality(enabled) {
227
+ log(`Turning basic functionality: ${enabled ? 'ON' : 'OFF'}`);
221
228
  // Loop through providers and enable/disable only wrapped ones when basic functionality changes
222
229
  for (const provider of __classPrivateFieldGet(this, _MultichainAccountService_providers, "f")) {
223
230
  if (isAccountProviderWrapper(provider)) {
231
+ log(`${enabled ? 'Enabling' : 'Disabling'} account provider: "${provider.getName()}"`);
224
232
  provider.setEnabled(enabled);
225
233
  }
226
234
  // Regular providers (like EVM) are never disabled for basic functionality
@@ -234,8 +242,10 @@ export class MultichainAccountService {
234
242
  * Align all multichain account wallets.
235
243
  */
236
244
  async alignWallets() {
245
+ log(`Triggering alignment on all wallets...`);
237
246
  const wallets = this.getMultichainAccountWallets();
238
247
  await Promise.all(wallets.map((w) => w.alignAccounts()));
248
+ log(`Wallets aligned`);
239
249
  }
240
250
  /**
241
251
  * Align a specific multichain account wallet.
@@ -244,7 +254,9 @@ export class MultichainAccountService {
244
254
  */
245
255
  async alignWallet(entropySource) {
246
256
  const wallet = this.getMultichainAccountWallet({ entropySource });
257
+ log(`Triggering alignment for wallet: [${wallet.id}]`);
247
258
  await wallet.alignAccounts();
259
+ log(`Wallet [${wallet.id}] aligned`);
248
260
  }
249
261
  }
250
262
  _MultichainAccountService_messenger = new WeakMap(), _MultichainAccountService_providers = new WeakMap(), _MultichainAccountService_wallets = new WeakMap(), _MultichainAccountService_accountIdToContext = new WeakMap(), _MultichainAccountService_instances = new WeakSet(), _MultichainAccountService_handleOnAccountAdded = function _MultichainAccountService_handleOnAccountAdded(account) {
@@ -255,6 +267,7 @@ _MultichainAccountService_messenger = new WeakMap(), _MultichainAccountService_p
255
267
  let sync = true;
256
268
  let wallet = __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").get(toMultichainAccountWalletId(account.options.entropy.id));
257
269
  if (!wallet) {
270
+ log(`Adding new wallet for entropy: "${account.options.entropy.id}" (for account: "${account.id}")`);
258
271
  // That's a new wallet.
259
272
  wallet = new MultichainAccountWallet({
260
273
  entropySource: account.options.entropy.id,
@@ -294,6 +307,7 @@ _MultichainAccountService_messenger = new WeakMap(), _MultichainAccountService_p
294
307
  const found = __classPrivateFieldGet(this, _MultichainAccountService_accountIdToContext, "f").get(id);
295
308
  if (found) {
296
309
  const { wallet } = found;
310
+ log(`Re-synchronize wallet [${wallet.id}] since account "${id}" got removed`);
297
311
  wallet.sync();
298
312
  }
299
313
  // Safe to call delete even if the `id` was not referencing a BIP-44 account.
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountService.mjs","sourceRoot":"","sources":["../src/MultichainAccountService.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isBip44Account,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport type {\n MultichainAccountWalletId,\n Bip44Account,\n} from '@metamask/account-api';\nimport type { HdKeyring } from '@metamask/eth-hd-keyring';\nimport { mnemonicPhraseToBytes } from '@metamask/key-tree';\nimport type { EntropySourceId, KeyringAccount } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport { areUint8ArraysEqual } from '@metamask/utils';\n\nimport type { MultichainAccountGroup } from './MultichainAccountGroup';\nimport { MultichainAccountWallet } from './MultichainAccountWallet';\nimport type {\n EvmAccountProviderConfig,\n NamedAccountProvider,\n SolAccountProviderConfig,\n} from './providers';\nimport {\n AccountProviderWrapper,\n isAccountProviderWrapper,\n} from './providers/AccountProviderWrapper';\nimport { EvmAccountProvider } from './providers/EvmAccountProvider';\nimport { SolAccountProvider } from './providers/SolAccountProvider';\nimport type { MultichainAccountServiceMessenger } from './types';\n\nexport const serviceName = 'MultichainAccountService';\n\n/**\n * The options that {@link MultichainAccountService} takes.\n */\nexport type MultichainAccountServiceOptions = {\n messenger: MultichainAccountServiceMessenger;\n providers?: NamedAccountProvider[];\n providerConfigs?: {\n [EvmAccountProvider.NAME]?: EvmAccountProviderConfig;\n [SolAccountProvider.NAME]?: SolAccountProviderConfig;\n };\n};\n\n/** Reverse mapping object used to map account IDs and their wallet/multichain account. */\ntype AccountContext<Account extends Bip44Account<KeyringAccount>> = {\n wallet: MultichainAccountWallet<Account>;\n group: MultichainAccountGroup<Account>;\n};\n\n/**\n * Service to expose multichain accounts capabilities.\n */\nexport class MultichainAccountService {\n readonly #messenger: MultichainAccountServiceMessenger;\n\n readonly #providers: NamedAccountProvider[];\n\n readonly #wallets: Map<\n MultichainAccountWalletId,\n MultichainAccountWallet<Bip44Account<KeyringAccount>>\n >;\n\n readonly #accountIdToContext: Map<\n Bip44Account<KeyringAccount>['id'],\n AccountContext<Bip44Account<KeyringAccount>>\n >;\n\n /**\n * The name of the service.\n */\n name: typeof serviceName = serviceName;\n\n /**\n * Constructs a new MultichainAccountService.\n *\n * @param options - The options.\n * @param options.messenger - The messenger suited to this\n * MultichainAccountService.\n * @param options.providers - Optional list of account\n * @param options.providerConfigs - Optional provider configs\n * providers.\n */\n constructor({\n messenger,\n providers = [],\n providerConfigs,\n }: MultichainAccountServiceOptions) {\n this.#messenger = messenger;\n this.#wallets = new Map();\n this.#accountIdToContext = new Map();\n\n // TODO: Rely on keyring capabilities once the keyring API is used by all keyrings.\n this.#providers = [\n new EvmAccountProvider(\n this.#messenger,\n providerConfigs?.[EvmAccountProvider.NAME],\n ),\n new AccountProviderWrapper(\n this.#messenger,\n new SolAccountProvider(\n this.#messenger,\n providerConfigs?.[SolAccountProvider.NAME],\n ),\n ),\n // Custom account providers that can be provided by the MetaMask client.\n ...providers,\n ];\n\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountGroup',\n (...args) => this.getMultichainAccountGroup(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountGroups',\n (...args) => this.getMultichainAccountGroups(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountWallet',\n (...args) => this.getMultichainAccountWallet(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountWallets',\n (...args) => this.getMultichainAccountWallets(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:createNextMultichainAccountGroup',\n (...args) => this.createNextMultichainAccountGroup(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:createMultichainAccountGroup',\n (...args) => this.createMultichainAccountGroup(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:setBasicFunctionality',\n (...args) => this.setBasicFunctionality(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:alignWallets',\n (...args) => this.alignWallets(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:alignWallet',\n (...args) => this.alignWallet(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:createMultichainAccountWallet',\n (...args) => this.createMultichainAccountWallet(...args),\n );\n\n this.#messenger.subscribe('AccountsController:accountAdded', (account) =>\n this.#handleOnAccountAdded(account),\n );\n this.#messenger.subscribe('AccountsController:accountRemoved', (id) =>\n this.#handleOnAccountRemoved(id),\n );\n }\n\n /**\n * Initialize the service and constructs the internal reprensentation of\n * multichain accounts and wallets.\n */\n init(): void {\n this.#wallets.clear();\n this.#accountIdToContext.clear();\n\n // Create initial wallets.\n const { keyrings } = this.#messenger.call('KeyringController:getState');\n for (const keyring of keyrings) {\n if (keyring.type === (KeyringTypes.hd as string)) {\n // Only HD keyrings have an entropy source/SRP.\n const entropySource = keyring.metadata.id;\n\n // This will automatically \"associate\" all multichain accounts for that wallet\n // (based on the accounts owned by each account providers).\n const wallet = new MultichainAccountWallet({\n entropySource,\n providers: this.#providers,\n messenger: this.#messenger,\n });\n this.#wallets.set(wallet.id, wallet);\n\n // Reverse mapping between account ID and their multichain wallet/account:\n for (const group of wallet.getMultichainAccountGroups()) {\n for (const account of group.getAccounts()) {\n this.#accountIdToContext.set(account.id, {\n wallet,\n group,\n });\n }\n }\n }\n }\n }\n\n #handleOnAccountAdded(account: KeyringAccount): void {\n // We completely omit non-BIP-44 accounts!\n if (!isBip44Account(account)) {\n return;\n }\n\n let sync = true;\n\n let wallet = this.#wallets.get(\n toMultichainAccountWalletId(account.options.entropy.id),\n );\n if (!wallet) {\n // That's a new wallet.\n wallet = new MultichainAccountWallet({\n entropySource: account.options.entropy.id,\n providers: this.#providers,\n messenger: this.#messenger,\n });\n this.#wallets.set(wallet.id, wallet);\n\n // If that's a new wallet wallet. There's nothing to \"force-sync\".\n sync = false;\n }\n\n let group = wallet.getMultichainAccountGroup(\n account.options.entropy.groupIndex,\n );\n if (!group) {\n // This new account is a new multichain account, let the wallet know\n // it has to re-sync with its providers.\n if (sync) {\n wallet.sync();\n }\n\n group = wallet.getMultichainAccountGroup(\n account.options.entropy.groupIndex,\n );\n\n // If that's a new multichain account. There's nothing to \"force-sync\".\n sync = false;\n }\n\n // We have to check against `undefined` in case `getMultichainAccount` is\n // not able to find this multichain account (which should not be possible...)\n if (group) {\n if (sync) {\n group.sync();\n }\n\n // Same here, this account should have been already grouped in that\n // multichain account.\n this.#accountIdToContext.set(account.id, {\n wallet,\n group,\n });\n }\n }\n\n #handleOnAccountRemoved(id: KeyringAccount['id']): void {\n // Force sync of the appropriate wallet if an account got removed.\n const found = this.#accountIdToContext.get(id);\n if (found) {\n const { wallet } = found;\n\n wallet.sync();\n }\n\n // Safe to call delete even if the `id` was not referencing a BIP-44 account.\n this.#accountIdToContext.delete(id);\n }\n\n #getWallet(\n entropySource: EntropySourceId,\n ): MultichainAccountWallet<Bip44Account<KeyringAccount>> {\n const wallet = this.#wallets.get(\n toMultichainAccountWalletId(entropySource),\n );\n\n if (!wallet) {\n throw new Error('Unknown wallet, no wallet matching this entropy source');\n }\n\n return wallet;\n }\n\n /**\n * Gets the account's context which contains its multichain wallet and\n * multichain account group references.\n *\n * @param id - Account ID.\n * @returns The account context if any, undefined otherwise.\n */\n getAccountContext(\n id: KeyringAccount['id'],\n ): AccountContext<Bip44Account<KeyringAccount>> | undefined {\n return this.#accountIdToContext.get(id);\n }\n\n /**\n * Gets a reference to the multichain account wallet matching this entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @throws If none multichain account match this entropy.\n * @returns A reference to the multichain account wallet.\n */\n getMultichainAccountWallet({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccountWallet<Bip44Account<KeyringAccount>> {\n return this.#getWallet(entropySource);\n }\n\n /**\n * Gets an array of all multichain account wallets.\n *\n * @returns An array of all multichain account wallets.\n */\n getMultichainAccountWallets(): MultichainAccountWallet<\n Bip44Account<KeyringAccount>\n >[] {\n return Array.from(this.#wallets.values());\n }\n\n /**\n * Creates a new multichain account wallet with the given mnemonic.\n *\n * NOTE: This method should only be called in client code where a mutex lock is acquired.\n * `discoverAndCreateAccounts` should be called after this method to discover and create accounts.\n *\n * @param options - Options.\n * @param options.mnemonic - The mnemonic to use to create the new wallet.\n * @throws If the mnemonic has already been imported.\n * @returns The new multichain account wallet.\n */\n async createMultichainAccountWallet({\n mnemonic,\n }: {\n mnemonic: string;\n }): Promise<MultichainAccountWallet<Bip44Account<KeyringAccount>>> {\n const existingKeyrings = this.#messenger.call(\n 'KeyringController:getKeyringsByType',\n KeyringTypes.hd,\n ) as HdKeyring[];\n\n const mnemonicAsBytes = mnemonicPhraseToBytes(mnemonic);\n\n const alreadyHasImportedSrp = existingKeyrings.some((keyring) => {\n if (!keyring.mnemonic) {\n return false;\n }\n return areUint8ArraysEqual(keyring.mnemonic, mnemonicAsBytes);\n });\n\n if (alreadyHasImportedSrp) {\n throw new Error('This Secret Recovery Phrase has already been imported.');\n }\n\n const result = await this.#messenger.call(\n 'KeyringController:addNewKeyring',\n KeyringTypes.hd,\n { mnemonic },\n );\n\n const wallet = new MultichainAccountWallet({\n providers: this.#providers,\n entropySource: result.id,\n messenger: this.#messenger,\n });\n\n this.#wallets.set(wallet.id, wallet);\n\n return wallet;\n }\n\n /**\n * Gets a reference to the multichain account group matching this entropy source\n * and a group index.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @param options.groupIndex - The group index of the multichain account.\n * @throws If none multichain account match this entropy source and group index.\n * @returns A reference to the multichain account.\n */\n getMultichainAccountGroup({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): MultichainAccountGroup<Bip44Account<KeyringAccount>> {\n const multichainAccount =\n this.#getWallet(entropySource).getMultichainAccountGroup(groupIndex);\n\n if (!multichainAccount) {\n throw new Error(`No multichain account for index: ${groupIndex}`);\n }\n\n return multichainAccount;\n }\n\n /**\n * Gets all multichain account groups for a given entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source to query.\n * @throws If no multichain accounts match this entropy source.\n * @returns A list of all multichain accounts.\n */\n getMultichainAccountGroups({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccountGroup<Bip44Account<KeyringAccount>>[] {\n return this.#getWallet(entropySource).getMultichainAccountGroups();\n }\n\n /**\n * Creates the next multichain account group.\n *\n * @param options - Options.\n * @param options.entropySource - The wallet's entropy source.\n * @returns The next multichain account group.\n */\n async createNextMultichainAccountGroup({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): Promise<MultichainAccountGroup<Bip44Account<KeyringAccount>>> {\n return await this.#getWallet(\n entropySource,\n ).createNextMultichainAccountGroup();\n }\n\n /**\n * Creates a multichain account group.\n *\n * @param options - Options.\n * @param options.groupIndex - The group index to use.\n * @param options.entropySource - The wallet's entropy source.\n * @returns The multichain account group for this group index.\n */\n async createMultichainAccountGroup({\n groupIndex,\n entropySource,\n }: {\n groupIndex: number;\n entropySource: EntropySourceId;\n }): Promise<MultichainAccountGroup<Bip44Account<KeyringAccount>>> {\n return await this.#getWallet(entropySource).createMultichainAccountGroup(\n groupIndex,\n );\n }\n\n /**\n * Set basic functionality state and trigger alignment if enabled.\n * When basic functionality is disabled, snap-based providers are disabled.\n * When enabled, all snap providers are enabled and wallet alignment is triggered.\n * EVM providers are never disabled as they're required for basic wallet functionality.\n *\n * @param enabled - Whether basic functionality is enabled.\n */\n async setBasicFunctionality(enabled: boolean): Promise<void> {\n // Loop through providers and enable/disable only wrapped ones when basic functionality changes\n for (const provider of this.#providers) {\n if (isAccountProviderWrapper(provider)) {\n provider.setEnabled(enabled);\n }\n // Regular providers (like EVM) are never disabled for basic functionality\n }\n\n // Trigger alignment only when basic functionality is enabled\n if (enabled) {\n await this.alignWallets();\n }\n }\n\n /**\n * Align all multichain account wallets.\n */\n async alignWallets(): Promise<void> {\n const wallets = this.getMultichainAccountWallets();\n await Promise.all(wallets.map((w) => w.alignAccounts()));\n }\n\n /**\n * Align a specific multichain account wallet.\n *\n * @param entropySource - The entropy source of the multichain account wallet.\n */\n async alignWallet(entropySource: EntropySourceId): Promise<void> {\n const wallet = this.getMultichainAccountWallet({ entropySource });\n await wallet.alignAccounts();\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainAccountService.mjs","sourceRoot":"","sources":["../src/MultichainAccountService.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isBip44Account,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport type {\n MultichainAccountWalletId,\n Bip44Account,\n} from '@metamask/account-api';\nimport type { HdKeyring } from '@metamask/eth-hd-keyring';\nimport { mnemonicPhraseToBytes } from '@metamask/key-tree';\nimport type { EntropySourceId, KeyringAccount } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport { areUint8ArraysEqual } from '@metamask/utils';\n\nimport { projectLogger as log } from './logger';\nimport type { MultichainAccountGroup } from './MultichainAccountGroup';\nimport { MultichainAccountWallet } from './MultichainAccountWallet';\nimport type {\n EvmAccountProviderConfig,\n NamedAccountProvider,\n SolAccountProviderConfig,\n} from './providers';\nimport {\n AccountProviderWrapper,\n isAccountProviderWrapper,\n} from './providers/AccountProviderWrapper';\nimport { EvmAccountProvider } from './providers/EvmAccountProvider';\nimport { SolAccountProvider } from './providers/SolAccountProvider';\nimport type { MultichainAccountServiceMessenger } from './types';\n\nexport const serviceName = 'MultichainAccountService';\n\n/**\n * The options that {@link MultichainAccountService} takes.\n */\nexport type MultichainAccountServiceOptions = {\n messenger: MultichainAccountServiceMessenger;\n providers?: NamedAccountProvider[];\n providerConfigs?: {\n [EvmAccountProvider.NAME]?: EvmAccountProviderConfig;\n [SolAccountProvider.NAME]?: SolAccountProviderConfig;\n };\n};\n\n/** Reverse mapping object used to map account IDs and their wallet/multichain account. */\ntype AccountContext<Account extends Bip44Account<KeyringAccount>> = {\n wallet: MultichainAccountWallet<Account>;\n group: MultichainAccountGroup<Account>;\n};\n\n/**\n * Service to expose multichain accounts capabilities.\n */\nexport class MultichainAccountService {\n readonly #messenger: MultichainAccountServiceMessenger;\n\n readonly #providers: NamedAccountProvider[];\n\n readonly #wallets: Map<\n MultichainAccountWalletId,\n MultichainAccountWallet<Bip44Account<KeyringAccount>>\n >;\n\n readonly #accountIdToContext: Map<\n Bip44Account<KeyringAccount>['id'],\n AccountContext<Bip44Account<KeyringAccount>>\n >;\n\n /**\n * The name of the service.\n */\n name: typeof serviceName = serviceName;\n\n /**\n * Constructs a new MultichainAccountService.\n *\n * @param options - The options.\n * @param options.messenger - The messenger suited to this\n * MultichainAccountService.\n * @param options.providers - Optional list of account\n * @param options.providerConfigs - Optional provider configs\n * providers.\n */\n constructor({\n messenger,\n providers = [],\n providerConfigs,\n }: MultichainAccountServiceOptions) {\n this.#messenger = messenger;\n this.#wallets = new Map();\n this.#accountIdToContext = new Map();\n\n // TODO: Rely on keyring capabilities once the keyring API is used by all keyrings.\n this.#providers = [\n new EvmAccountProvider(\n this.#messenger,\n providerConfigs?.[EvmAccountProvider.NAME],\n ),\n new AccountProviderWrapper(\n this.#messenger,\n new SolAccountProvider(\n this.#messenger,\n providerConfigs?.[SolAccountProvider.NAME],\n ),\n ),\n // Custom account providers that can be provided by the MetaMask client.\n ...providers,\n ];\n\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountGroup',\n (...args) => this.getMultichainAccountGroup(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountGroups',\n (...args) => this.getMultichainAccountGroups(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountWallet',\n (...args) => this.getMultichainAccountWallet(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:getMultichainAccountWallets',\n (...args) => this.getMultichainAccountWallets(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:createNextMultichainAccountGroup',\n (...args) => this.createNextMultichainAccountGroup(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:createMultichainAccountGroup',\n (...args) => this.createMultichainAccountGroup(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:setBasicFunctionality',\n (...args) => this.setBasicFunctionality(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:alignWallets',\n (...args) => this.alignWallets(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:alignWallet',\n (...args) => this.alignWallet(...args),\n );\n this.#messenger.registerActionHandler(\n 'MultichainAccountService:createMultichainAccountWallet',\n (...args) => this.createMultichainAccountWallet(...args),\n );\n\n this.#messenger.subscribe('AccountsController:accountAdded', (account) =>\n this.#handleOnAccountAdded(account),\n );\n this.#messenger.subscribe('AccountsController:accountRemoved', (id) =>\n this.#handleOnAccountRemoved(id),\n );\n }\n\n /**\n * Initialize the service and constructs the internal reprensentation of\n * multichain accounts and wallets.\n */\n init(): void {\n log('Initializing...');\n\n this.#wallets.clear();\n this.#accountIdToContext.clear();\n\n // Create initial wallets.\n const { keyrings } = this.#messenger.call('KeyringController:getState');\n for (const keyring of keyrings) {\n if (keyring.type === (KeyringTypes.hd as string)) {\n // Only HD keyrings have an entropy source/SRP.\n const entropySource = keyring.metadata.id;\n\n log(`Adding new wallet for entropy: \"${entropySource}\"`);\n\n // This will automatically \"associate\" all multichain accounts for that wallet\n // (based on the accounts owned by each account providers).\n const wallet = new MultichainAccountWallet({\n entropySource,\n providers: this.#providers,\n messenger: this.#messenger,\n });\n this.#wallets.set(wallet.id, wallet);\n\n // Reverse mapping between account ID and their multichain wallet/account:\n for (const group of wallet.getMultichainAccountGroups()) {\n for (const account of group.getAccounts()) {\n this.#accountIdToContext.set(account.id, {\n wallet,\n group,\n });\n }\n }\n }\n }\n\n log('Initialized');\n }\n\n #handleOnAccountAdded(account: KeyringAccount): void {\n // We completely omit non-BIP-44 accounts!\n if (!isBip44Account(account)) {\n return;\n }\n\n let sync = true;\n\n let wallet = this.#wallets.get(\n toMultichainAccountWalletId(account.options.entropy.id),\n );\n if (!wallet) {\n log(\n `Adding new wallet for entropy: \"${account.options.entropy.id}\" (for account: \"${account.id}\")`,\n );\n\n // That's a new wallet.\n wallet = new MultichainAccountWallet({\n entropySource: account.options.entropy.id,\n providers: this.#providers,\n messenger: this.#messenger,\n });\n this.#wallets.set(wallet.id, wallet);\n\n // If that's a new wallet wallet. There's nothing to \"force-sync\".\n sync = false;\n }\n\n let group = wallet.getMultichainAccountGroup(\n account.options.entropy.groupIndex,\n );\n if (!group) {\n // This new account is a new multichain account, let the wallet know\n // it has to re-sync with its providers.\n if (sync) {\n wallet.sync();\n }\n\n group = wallet.getMultichainAccountGroup(\n account.options.entropy.groupIndex,\n );\n\n // If that's a new multichain account. There's nothing to \"force-sync\".\n sync = false;\n }\n\n // We have to check against `undefined` in case `getMultichainAccount` is\n // not able to find this multichain account (which should not be possible...)\n if (group) {\n if (sync) {\n group.sync();\n }\n\n // Same here, this account should have been already grouped in that\n // multichain account.\n this.#accountIdToContext.set(account.id, {\n wallet,\n group,\n });\n }\n }\n\n #handleOnAccountRemoved(id: KeyringAccount['id']): void {\n // Force sync of the appropriate wallet if an account got removed.\n const found = this.#accountIdToContext.get(id);\n if (found) {\n const { wallet } = found;\n\n log(\n `Re-synchronize wallet [${wallet.id}] since account \"${id}\" got removed`,\n );\n wallet.sync();\n }\n\n // Safe to call delete even if the `id` was not referencing a BIP-44 account.\n this.#accountIdToContext.delete(id);\n }\n\n #getWallet(\n entropySource: EntropySourceId,\n ): MultichainAccountWallet<Bip44Account<KeyringAccount>> {\n const wallet = this.#wallets.get(\n toMultichainAccountWalletId(entropySource),\n );\n\n if (!wallet) {\n throw new Error('Unknown wallet, no wallet matching this entropy source');\n }\n\n return wallet;\n }\n\n /**\n * Gets the account's context which contains its multichain wallet and\n * multichain account group references.\n *\n * @param id - Account ID.\n * @returns The account context if any, undefined otherwise.\n */\n getAccountContext(\n id: KeyringAccount['id'],\n ): AccountContext<Bip44Account<KeyringAccount>> | undefined {\n return this.#accountIdToContext.get(id);\n }\n\n /**\n * Gets a reference to the multichain account wallet matching this entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @throws If none multichain account match this entropy.\n * @returns A reference to the multichain account wallet.\n */\n getMultichainAccountWallet({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccountWallet<Bip44Account<KeyringAccount>> {\n return this.#getWallet(entropySource);\n }\n\n /**\n * Gets an array of all multichain account wallets.\n *\n * @returns An array of all multichain account wallets.\n */\n getMultichainAccountWallets(): MultichainAccountWallet<\n Bip44Account<KeyringAccount>\n >[] {\n return Array.from(this.#wallets.values());\n }\n\n /**\n * Creates a new multichain account wallet with the given mnemonic.\n *\n * NOTE: This method should only be called in client code where a mutex lock is acquired.\n * `discoverAndCreateAccounts` should be called after this method to discover and create accounts.\n *\n * @param options - Options.\n * @param options.mnemonic - The mnemonic to use to create the new wallet.\n * @throws If the mnemonic has already been imported.\n * @returns The new multichain account wallet.\n */\n async createMultichainAccountWallet({\n mnemonic,\n }: {\n mnemonic: string;\n }): Promise<MultichainAccountWallet<Bip44Account<KeyringAccount>>> {\n const existingKeyrings = this.#messenger.call(\n 'KeyringController:getKeyringsByType',\n KeyringTypes.hd,\n ) as HdKeyring[];\n\n const mnemonicAsBytes = mnemonicPhraseToBytes(mnemonic);\n\n const alreadyHasImportedSrp = existingKeyrings.some((keyring) => {\n if (!keyring.mnemonic) {\n return false;\n }\n return areUint8ArraysEqual(keyring.mnemonic, mnemonicAsBytes);\n });\n\n if (alreadyHasImportedSrp) {\n throw new Error('This Secret Recovery Phrase has already been imported.');\n }\n\n log(`Creating new wallet...`);\n\n const result = await this.#messenger.call(\n 'KeyringController:addNewKeyring',\n KeyringTypes.hd,\n { mnemonic },\n );\n\n const wallet = new MultichainAccountWallet({\n providers: this.#providers,\n entropySource: result.id,\n messenger: this.#messenger,\n });\n\n this.#wallets.set(wallet.id, wallet);\n\n log(`Wallet created: [${wallet.id}]`);\n\n return wallet;\n }\n\n /**\n * Gets a reference to the multichain account group matching this entropy source\n * and a group index.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @param options.groupIndex - The group index of the multichain account.\n * @throws If none multichain account match this entropy source and group index.\n * @returns A reference to the multichain account.\n */\n getMultichainAccountGroup({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): MultichainAccountGroup<Bip44Account<KeyringAccount>> {\n const multichainAccount =\n this.#getWallet(entropySource).getMultichainAccountGroup(groupIndex);\n\n if (!multichainAccount) {\n throw new Error(`No multichain account for index: ${groupIndex}`);\n }\n\n return multichainAccount;\n }\n\n /**\n * Gets all multichain account groups for a given entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source to query.\n * @throws If no multichain accounts match this entropy source.\n * @returns A list of all multichain accounts.\n */\n getMultichainAccountGroups({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccountGroup<Bip44Account<KeyringAccount>>[] {\n return this.#getWallet(entropySource).getMultichainAccountGroups();\n }\n\n /**\n * Creates the next multichain account group.\n *\n * @param options - Options.\n * @param options.entropySource - The wallet's entropy source.\n * @returns The next multichain account group.\n */\n async createNextMultichainAccountGroup({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): Promise<MultichainAccountGroup<Bip44Account<KeyringAccount>>> {\n return await this.#getWallet(\n entropySource,\n ).createNextMultichainAccountGroup();\n }\n\n /**\n * Creates a multichain account group.\n *\n * @param options - Options.\n * @param options.groupIndex - The group index to use.\n * @param options.entropySource - The wallet's entropy source.\n * @returns The multichain account group for this group index.\n */\n async createMultichainAccountGroup({\n groupIndex,\n entropySource,\n }: {\n groupIndex: number;\n entropySource: EntropySourceId;\n }): Promise<MultichainAccountGroup<Bip44Account<KeyringAccount>>> {\n return await this.#getWallet(entropySource).createMultichainAccountGroup(\n groupIndex,\n );\n }\n\n /**\n * Set basic functionality state and trigger alignment if enabled.\n * When basic functionality is disabled, snap-based providers are disabled.\n * When enabled, all snap providers are enabled and wallet alignment is triggered.\n * EVM providers are never disabled as they're required for basic wallet functionality.\n *\n * @param enabled - Whether basic functionality is enabled.\n */\n async setBasicFunctionality(enabled: boolean): Promise<void> {\n log(`Turning basic functionality: ${enabled ? 'ON' : 'OFF'}`);\n\n // Loop through providers and enable/disable only wrapped ones when basic functionality changes\n for (const provider of this.#providers) {\n if (isAccountProviderWrapper(provider)) {\n log(\n `${enabled ? 'Enabling' : 'Disabling'} account provider: \"${provider.getName()}\"`,\n );\n provider.setEnabled(enabled);\n }\n // Regular providers (like EVM) are never disabled for basic functionality\n }\n\n // Trigger alignment only when basic functionality is enabled\n if (enabled) {\n await this.alignWallets();\n }\n }\n\n /**\n * Align all multichain account wallets.\n */\n async alignWallets(): Promise<void> {\n log(`Triggering alignment on all wallets...`);\n\n const wallets = this.getMultichainAccountWallets();\n await Promise.all(wallets.map((w) => w.alignAccounts()));\n\n log(`Wallets aligned`);\n }\n\n /**\n * Align a specific multichain account wallet.\n *\n * @param entropySource - The entropy source of the multichain account wallet.\n */\n async alignWallet(entropySource: EntropySourceId): Promise<void> {\n const wallet = this.getMultichainAccountWallet({ entropySource });\n\n log(`Triggering alignment for wallet: [${wallet.id}]`);\n await wallet.alignAccounts();\n log(`Wallet [${wallet.id}] aligned`);\n }\n}\n"]}
@@ -10,16 +10,15 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _MultichainAccountWallet_instances, _MultichainAccountWallet_lock, _MultichainAccountWallet_id, _MultichainAccountWallet_providers, _MultichainAccountWallet_entropySource, _MultichainAccountWallet_accountGroups, _MultichainAccountWallet_messenger, _MultichainAccountWallet_initialized, _MultichainAccountWallet_status, _MultichainAccountWallet_withLock, _MultichainAccountWallet_alignAccounts;
13
+ var _MultichainAccountWallet_instances, _MultichainAccountWallet_lock, _MultichainAccountWallet_id, _MultichainAccountWallet_providers, _MultichainAccountWallet_entropySource, _MultichainAccountWallet_accountGroups, _MultichainAccountWallet_messenger, _MultichainAccountWallet_log, _MultichainAccountWallet_initialized, _MultichainAccountWallet_status, _MultichainAccountWallet_withLock, _MultichainAccountWallet_alignAccounts;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.MultichainAccountWallet = 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 account_api_3 = require("@metamask/account-api");
19
- const utils_1 = require("@metamask/utils");
20
19
  const async_mutex_1 = require("async-mutex");
20
+ const logger_1 = require("./logger.cjs");
21
21
  const MultichainAccountGroup_1 = require("./MultichainAccountGroup.cjs");
22
- const log = (0, utils_1.createProjectLogger)('multichain-account-service');
23
22
  /**
24
23
  * A multichain account wallet that holds multiple multichain accounts (one multichain account per
25
24
  * group index).
@@ -33,6 +32,7 @@ class MultichainAccountWallet {
33
32
  _MultichainAccountWallet_entropySource.set(this, void 0);
34
33
  _MultichainAccountWallet_accountGroups.set(this, void 0);
35
34
  _MultichainAccountWallet_messenger.set(this, void 0);
35
+ _MultichainAccountWallet_log.set(this, void 0);
36
36
  // eslint-disable-next-line @typescript-eslint/prefer-readonly
37
37
  _MultichainAccountWallet_initialized.set(this, false);
38
38
  _MultichainAccountWallet_status.set(this, void 0);
@@ -41,6 +41,7 @@ class MultichainAccountWallet {
41
41
  __classPrivateFieldSet(this, _MultichainAccountWallet_entropySource, entropySource, "f");
42
42
  __classPrivateFieldSet(this, _MultichainAccountWallet_messenger, messenger, "f");
43
43
  __classPrivateFieldSet(this, _MultichainAccountWallet_accountGroups, new Map(), "f");
44
+ __classPrivateFieldSet(this, _MultichainAccountWallet_log, (0, logger_1.createModuleLogger)(logger_1.projectLogger, `[${__classPrivateFieldGet(this, _MultichainAccountWallet_id, "f")}]`), "f");
44
45
  // Initial synchronization (don't emit events during initialization).
45
46
  __classPrivateFieldSet(this, _MultichainAccountWallet_status, 'uninitialized', "f");
46
47
  this.sync();
@@ -54,6 +55,7 @@ class MultichainAccountWallet {
54
55
  * doesn't know about.
55
56
  */
56
57
  sync() {
58
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, 'Synchronizing with account providers...');
57
59
  for (const provider of __classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f")) {
58
60
  for (const account of provider.getAccounts()) {
59
61
  const { entropy } = account.options;
@@ -79,6 +81,7 @@ class MultichainAccountWallet {
79
81
  // Since "aligning" is an async operation, it would have to be run
80
82
  // after the first-sync.
81
83
  // TODO: Implement align mechanism to create "missing" accounts.
84
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, `Found a new group: [${multichainAccount.id}]`);
82
85
  __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").set(entropy.groupIndex, multichainAccount);
83
86
  }
84
87
  }
@@ -88,9 +91,11 @@ class MultichainAccountWallet {
88
91
  multichainAccount.sync();
89
92
  // Clean up old multichain accounts.
90
93
  if (!multichainAccount.hasAccounts()) {
94
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, `Deleting group: [${multichainAccount.id}]`);
91
95
  __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").delete(groupIndex);
92
96
  }
93
97
  }
98
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, 'Synchronized');
94
99
  }
95
100
  /**
96
101
  * Gets the multichain account wallet ID.
@@ -199,8 +204,10 @@ class MultichainAccountWallet {
199
204
  // If the group already exists, we just `sync` it and returns the same
200
205
  // reference.
201
206
  group.sync();
207
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, `Trying to re-create existing group: [${group.id}] (idempotent)`);
202
208
  return group;
203
209
  }
210
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, `Creating new group for index ${groupIndex}...`);
204
211
  const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountWallet_providers, "f").map((provider) => provider.createAccounts({
205
212
  entropySource: __classPrivateFieldGet(this, _MultichainAccountWallet_entropySource, "f"),
206
213
  groupIndex,
@@ -232,13 +239,14 @@ class MultichainAccountWallet {
232
239
  // NOTE: Some accounts might still have been created on other account providers. We
233
240
  // don't rollback them.
234
241
  const error = `Unable to create multichain account group for index: ${groupIndex}`;
235
- let warn = `${error}:`;
242
+ let message = `${error}:`;
236
243
  for (const result of results) {
237
244
  if (result.status === 'rejected') {
238
- warn += `\n- ${result.reason}`;
245
+ message += `\n- ${result.reason}`;
239
246
  }
240
247
  }
241
- console.warn(warn);
248
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, `${logger_1.WARNING_PREFIX} ${message}`);
249
+ console.warn(message);
242
250
  throw new Error(error);
243
251
  }
244
252
  // Because of the :accountAdded automatic sync, we might already have created the
@@ -255,6 +263,7 @@ class MultichainAccountWallet {
255
263
  }
256
264
  // Register the account to our internal map.
257
265
  __classPrivateFieldGet(this, _MultichainAccountWallet_accountGroups, "f").set(groupIndex, group); // `group` cannot be undefined here.
266
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, `New group created: [${group.id}]`);
258
267
  if (__classPrivateFieldGet(this, _MultichainAccountWallet_initialized, "f")) {
259
268
  __classPrivateFieldGet(this, _MultichainAccountWallet_messenger, "f").publish('MultichainAccountService:multichainAccountGroupCreated', group);
260
269
  }
@@ -309,11 +318,12 @@ class MultichainAccountWallet {
309
318
  let maxGroupIndex = this.getNextGroupIndex();
310
319
  // One serialized loop per provider; all run concurrently
311
320
  const runProviderDiscovery = async (context) => {
312
- const message = (stepName, groupIndex) => `[${context.provider.getName()}] Discovery ${stepName} (groupIndex=${groupIndex})`;
321
+ const providerName = context.provider.getName();
322
+ const message = (stepName, groupIndex) => `[${providerName}] Discovery ${stepName} for group index: ${groupIndex}`;
313
323
  while (!context.stopped) {
314
324
  // Fast‑forward to current high‑water mark
315
325
  const targetGroupIndex = Math.max(context.groupIndex, maxGroupIndex);
316
- log(message('STARTED', targetGroupIndex));
326
+ (0, logger_1.projectLogger)(message('started', targetGroupIndex));
317
327
  let accounts = [];
318
328
  try {
319
329
  accounts = await context.provider.discoverAccounts({
@@ -324,15 +334,15 @@ class MultichainAccountWallet {
324
334
  catch (error) {
325
335
  context.stopped = true;
326
336
  console.error(error);
327
- log(message('FAILED', targetGroupIndex), error);
337
+ (0, logger_1.projectLogger)(message(`failed (with: "${error.message}")`, targetGroupIndex), error);
328
338
  break;
329
339
  }
330
340
  if (!accounts.length) {
331
- log(message('STOPPED', targetGroupIndex));
341
+ (0, logger_1.projectLogger)(message('stopped (no accounts got discovered)', targetGroupIndex));
332
342
  context.stopped = true;
333
343
  break;
334
344
  }
335
- log(message('SUCCEEDED', targetGroupIndex));
345
+ (0, logger_1.projectLogger)(message('**succeeded**', targetGroupIndex));
336
346
  context.accounts = context.accounts.concat(accounts);
337
347
  const nextGroupIndex = targetGroupIndex + 1;
338
348
  context.groupIndex = nextGroupIndex;
@@ -360,7 +370,7 @@ class MultichainAccountWallet {
360
370
  }
361
371
  }
362
372
  exports.MultichainAccountWallet = MultichainAccountWallet;
363
- _MultichainAccountWallet_lock = new WeakMap(), _MultichainAccountWallet_id = new WeakMap(), _MultichainAccountWallet_providers = new WeakMap(), _MultichainAccountWallet_entropySource = new WeakMap(), _MultichainAccountWallet_accountGroups = new WeakMap(), _MultichainAccountWallet_messenger = new WeakMap(), _MultichainAccountWallet_initialized = new WeakMap(), _MultichainAccountWallet_status = new WeakMap(), _MultichainAccountWallet_instances = new WeakSet(), _MultichainAccountWallet_withLock =
373
+ _MultichainAccountWallet_lock = new WeakMap(), _MultichainAccountWallet_id = new WeakMap(), _MultichainAccountWallet_providers = new WeakMap(), _MultichainAccountWallet_entropySource = new WeakMap(), _MultichainAccountWallet_accountGroups = new WeakMap(), _MultichainAccountWallet_messenger = new WeakMap(), _MultichainAccountWallet_log = new WeakMap(), _MultichainAccountWallet_initialized = new WeakMap(), _MultichainAccountWallet_status = new WeakMap(), _MultichainAccountWallet_instances = new WeakSet(), _MultichainAccountWallet_withLock =
364
374
  /**
365
375
  * Set the wallet status and run the associated operation callback.
366
376
  *
@@ -372,6 +382,7 @@ _MultichainAccountWallet_lock = new WeakMap(), _MultichainAccountWallet_id = new
372
382
  async function _MultichainAccountWallet_withLock(status, operation) {
373
383
  const release = await __classPrivateFieldGet(this, _MultichainAccountWallet_lock, "f").acquire();
374
384
  try {
385
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, `Locking wallet with status "${status}"...`);
375
386
  __classPrivateFieldSet(this, _MultichainAccountWallet_status, status, "f");
376
387
  __classPrivateFieldGet(this, _MultichainAccountWallet_messenger, "f").publish('MultichainAccountService:walletStatusChange', this.id, __classPrivateFieldGet(this, _MultichainAccountWallet_status, "f"));
377
388
  return await operation();
@@ -380,6 +391,7 @@ async function _MultichainAccountWallet_withLock(status, operation) {
380
391
  __classPrivateFieldSet(this, _MultichainAccountWallet_status, 'ready', "f");
381
392
  __classPrivateFieldGet(this, _MultichainAccountWallet_messenger, "f").publish('MultichainAccountService:walletStatusChange', this.id, __classPrivateFieldGet(this, _MultichainAccountWallet_status, "f"));
382
393
  release();
394
+ __classPrivateFieldGet(this, _MultichainAccountWallet_log, "f").call(this, `Releasing wallet lock (was "${status}")`);
383
395
  }
384
396
  }, _MultichainAccountWallet_alignAccounts =
385
397
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountWallet.cjs","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getGroupIndexFromMultichainAccountGroupId,\n isMultichainAccountGroupId,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport { toDefaultAccountGroupId } from '@metamask/account-api';\nimport { AccountWalletType } from '@metamask/account-api';\nimport type {\n Bip44Account,\n MultichainAccountWalletId,\n MultichainAccountWallet as MultichainAccountWalletDefinition,\n MultichainAccountWalletStatus,\n} from '@metamask/account-api';\nimport type { AccountGroupId } from '@metamask/account-api';\nimport {\n type EntropySourceId,\n type KeyringAccount,\n} from '@metamask/keyring-api';\nimport { createProjectLogger } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport { MultichainAccountGroup } from './MultichainAccountGroup';\nimport type { NamedAccountProvider } from './providers';\nimport type { MultichainAccountServiceMessenger } from './types';\n\n/**\n * The context for a provider discovery.\n */\ntype AccountProviderDiscoveryContext<\n Account extends Bip44Account<KeyringAccount>,\n> = {\n provider: NamedAccountProvider<Account>;\n stopped: boolean;\n groupIndex: number;\n accounts: Account[];\n};\n\nconst log = createProjectLogger('multichain-account-service');\n\n/**\n * A multichain account wallet that holds multiple multichain accounts (one multichain account per\n * group index).\n */\nexport class MultichainAccountWallet<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountWalletDefinition<Account>\n{\n readonly #lock = new Mutex();\n\n readonly #id: MultichainAccountWalletId;\n\n readonly #providers: NamedAccountProvider<Account>[];\n\n readonly #entropySource: EntropySourceId;\n\n readonly #accountGroups: Map<number, MultichainAccountGroup<Account>>;\n\n readonly #messenger: MultichainAccountServiceMessenger;\n\n // eslint-disable-next-line @typescript-eslint/prefer-readonly\n #initialized = false;\n\n #status: MultichainAccountWalletStatus;\n\n constructor({\n providers,\n entropySource,\n messenger,\n }: {\n providers: NamedAccountProvider<Account>[];\n entropySource: EntropySourceId;\n messenger: MultichainAccountServiceMessenger;\n }) {\n this.#id = toMultichainAccountWalletId(entropySource);\n this.#providers = providers;\n this.#entropySource = entropySource;\n this.#messenger = messenger;\n this.#accountGroups = new Map();\n\n // Initial synchronization (don't emit events during initialization).\n this.#status = 'uninitialized';\n this.sync();\n this.#initialized = true;\n this.#status = 'ready';\n }\n\n /**\n * Force wallet synchronization.\n *\n * This can be used if account providers got new accounts that the wallet\n * doesn't know about.\n */\n sync(): void {\n for (const provider of this.#providers) {\n for (const account of provider.getAccounts()) {\n const { entropy } = account.options;\n\n // Filter for this wallet only.\n if (entropy.id !== this.entropySource) {\n continue;\n }\n\n // This multichain account might exists already.\n let multichainAccount = this.#accountGroups.get(entropy.groupIndex);\n if (!multichainAccount) {\n multichainAccount = new MultichainAccountGroup<Account>({\n groupIndex: entropy.groupIndex,\n wallet: this,\n providers: this.#providers,\n messenger: this.#messenger,\n });\n\n // This existing multichain account group might differ from the\n // `createMultichainAccountGroup` behavior. When creating a new\n // group, we expect the providers to all succeed. But here, we're\n // just fetching the account lists from them, so this group might\n // not be \"aligned\" yet (e.g having a missing Solana account).\n //\n // Since \"aligning\" is an async operation, it would have to be run\n // after the first-sync.\n // TODO: Implement align mechanism to create \"missing\" accounts.\n\n this.#accountGroups.set(entropy.groupIndex, multichainAccount);\n }\n }\n }\n\n // Now force-sync all remaining multichain accounts.\n for (const [\n groupIndex,\n multichainAccount,\n ] of this.#accountGroups.entries()) {\n multichainAccount.sync();\n\n // Clean up old multichain accounts.\n if (!multichainAccount.hasAccounts()) {\n this.#accountGroups.delete(groupIndex);\n }\n }\n }\n\n /**\n * Gets the multichain account wallet ID.\n *\n * @returns The multichain account wallet ID.\n */\n get id(): MultichainAccountWalletId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.\n *\n * @returns The multichain account wallet type.\n */\n get type(): AccountWalletType.Entropy {\n return AccountWalletType.Entropy;\n }\n\n /**\n * Gets the multichain account wallet entropy source.\n *\n * @returns The multichain account wallet entropy source.\n */\n get entropySource(): EntropySourceId {\n return this.#entropySource;\n }\n\n /**\n * Gets the multichain account wallet current status.\n *\n * @returns The multichain account wallet current status.\n */\n get status(): MultichainAccountWalletStatus {\n return this.#status;\n }\n\n /**\n * Set the wallet status and run the associated operation callback.\n *\n * @param status - Wallet status associated with this operation.\n * @param operation - Operation to run.\n * @returns The operation's result.\n * @throws {Error} If the wallet is already running a mutable operation.\n */\n async #withLock<Return>(\n status: MultichainAccountWalletStatus,\n operation: () => Promise<Return>,\n ) {\n const release = await this.#lock.acquire();\n try {\n this.#status = status;\n this.#messenger.publish(\n 'MultichainAccountService:walletStatusChange',\n this.id,\n this.#status,\n );\n return await operation();\n } finally {\n this.#status = 'ready';\n this.#messenger.publish(\n 'MultichainAccountService:walletStatusChange',\n this.id,\n this.#status,\n );\n release();\n }\n }\n\n /**\n * Gets multichain account for a given ID.\n * The default group ID will default to the multichain account with index 0.\n *\n * @param id - Account group ID.\n * @returns Account group.\n */\n getAccountGroup(\n id: AccountGroupId,\n ): MultichainAccountGroup<Account> | undefined {\n // We consider the \"default case\" to be mapped to index 0.\n if (id === toDefaultAccountGroupId(this.id)) {\n return this.#accountGroups.get(0);\n }\n\n // If it is not a valid ID, we cannot extract the group index\n // from it, so we fail fast.\n if (!isMultichainAccountGroupId(id)) {\n return undefined;\n }\n\n const groupIndex = getGroupIndexFromMultichainAccountGroupId(id);\n return this.#accountGroups.get(groupIndex);\n }\n\n /**\n * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.\n *\n * @returns The multichain accounts.\n */\n getAccountGroups(): MultichainAccountGroup<Account>[] {\n return this.getMultichainAccountGroups();\n }\n\n /**\n * Gets multichain account group for a given index.\n *\n * @param groupIndex - Multichain account index.\n * @returns The multichain account associated with the given index.\n */\n getMultichainAccountGroup(\n groupIndex: number,\n ): MultichainAccountGroup<Account> | undefined {\n return this.#accountGroups.get(groupIndex);\n }\n\n /**\n * Gets all multichain account groups.\n *\n * @returns The multichain accounts.\n */\n getMultichainAccountGroups(): MultichainAccountGroup<Account>[] {\n return Array.from(this.#accountGroups.values()); // TODO: Prevent copy here.\n }\n\n /**\n * Gets next group index for this wallet.\n *\n * @returns The next group index of this wallet.\n */\n getNextGroupIndex(): number {\n // We do not check for gaps.\n return (\n Math.max(\n -1, // So it will default to 0 if no groups.\n ...this.#accountGroups.keys(),\n ) + 1\n );\n }\n\n /**\n * Creates a multichain account group for a given group index.\n *\n * NOTE: This operation WILL lock the wallet's mutex.\n *\n * @param groupIndex - The group index to use.\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for this group index.\n */\n async createMultichainAccountGroup(\n groupIndex: number,\n ): Promise<MultichainAccountGroup<Account>> {\n return await this.#withLock('in-progress:create-accounts', async () => {\n const nextGroupIndex = this.getNextGroupIndex();\n if (groupIndex > nextGroupIndex) {\n throw new Error(\n `You cannot use a group index that is higher than the next available one: expected <=${nextGroupIndex}, got ${groupIndex}`,\n );\n }\n\n let group = this.getMultichainAccountGroup(groupIndex);\n if (group) {\n // If the group already exists, we just `sync` it and returns the same\n // reference.\n group.sync();\n\n return group;\n }\n\n const results = await Promise.allSettled(\n this.#providers.map((provider) =>\n provider.createAccounts({\n entropySource: this.#entropySource,\n groupIndex,\n }),\n ),\n );\n\n // --------------------------------------------------------------------------------\n // READ THIS CAREFULLY:\n //\n // Since we're not \"fully supporting multichain\" for now, we still rely on single\n // :accountCreated events to sync multichain account groups and wallets. Which means\n // that even if of the provider fails, some accounts will still be created on some\n // other providers and will become \"available\" on the `AccountsController`, like:\n //\n // 1. Creating a multichain account group for index 1\n // 2. EvmAccountProvider.createAccounts returns the EVM account for index 1\n // * AccountsController WILL fire :accountCreated for this account\n // * This account WILL BE \"available\" on the AccountsController state\n // 3. SolAccountProvider.createAccounts fails to create a Solana account for index 1\n // * AccountsController WON't fire :accountCreated for this account\n // * This account WON'T be \"available\" on the Account\n // 4. MultichainAccountService will receive a :accountCreated for the EVM account from\n // step 2 and will create a new multichain account group for index 1, but it won't\n // receive any event for the Solana account of this group. Thus, this group won't be\n // \"aligned\" (missing \"blockchain account\" on this group).\n //\n // --------------------------------------------------------------------------------\n\n // If any of the provider failed to create their accounts, then we consider the\n // multichain account group to have failed too.\n if (results.some((result) => result.status === 'rejected')) {\n // NOTE: Some accounts might still have been created on other account providers. We\n // don't rollback them.\n const error = `Unable to create multichain account group for index: ${groupIndex}`;\n\n let warn = `${error}:`;\n for (const result of results) {\n if (result.status === 'rejected') {\n warn += `\\n- ${result.reason}`;\n }\n }\n console.warn(warn);\n\n throw new Error(error);\n }\n\n // Because of the :accountAdded automatic sync, we might already have created the\n // group, so we first try to get it.\n group = this.getMultichainAccountGroup(groupIndex);\n if (!group) {\n // If for some reason it's still not created, we're creating it explicitly now:\n group = new MultichainAccountGroup({\n wallet: this,\n providers: this.#providers,\n groupIndex,\n messenger: this.#messenger,\n });\n }\n\n // Register the account to our internal map.\n this.#accountGroups.set(groupIndex, group); // `group` cannot be undefined here.\n\n if (this.#initialized) {\n this.#messenger.publish(\n 'MultichainAccountService:multichainAccountGroupCreated',\n group,\n );\n }\n\n return group;\n });\n }\n\n /**\n * Creates the next multichain account group.\n *\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for the next group index available.\n */\n async createNextMultichainAccountGroup(): Promise<\n MultichainAccountGroup<Account>\n > {\n return this.createMultichainAccountGroup(this.getNextGroupIndex());\n }\n\n /**\n * Align all multichain account groups.\n *\n * NOTE: This operation WILL NOT lock the wallet's mutex.\n */\n async #alignAccounts(): Promise<void> {\n const groups = this.getMultichainAccountGroups();\n await Promise.all(groups.map((group) => group.alignAccounts()));\n }\n\n /**\n * Align all accounts from each existing multichain account groups.\n *\n * NOTE: This operation WILL lock the wallet's mutex.\n */\n async alignAccounts(): Promise<void> {\n await this.#withLock('in-progress:alignment', async () => {\n await this.#alignAccounts();\n });\n }\n\n /**\n * Align a specific multichain account group.\n *\n * NOTE: This operation WILL lock the wallet's mutex.\n *\n * @param groupIndex - The group index to align.\n */\n async alignAccountsOf(groupIndex: number): Promise<void> {\n await this.#withLock('in-progress:alignment', async () => {\n const group = this.getMultichainAccountGroup(groupIndex);\n if (group) {\n await group.alignAccounts();\n }\n });\n }\n\n /**\n * Discover and create accounts for all providers.\n *\n * NOTE: This operation WILL lock the wallet's mutex.\n *\n * @returns The discovered accounts for each provider.\n */\n async discoverAccounts(): Promise<Account[]> {\n return this.#withLock('in-progress:discovery', async () => {\n // Start with the next available group index (so we can resume the discovery\n // from there).\n let maxGroupIndex = this.getNextGroupIndex();\n\n // One serialized loop per provider; all run concurrently\n const runProviderDiscovery = async (\n context: AccountProviderDiscoveryContext<Account>,\n ) => {\n const message = (stepName: string, groupIndex: number) =>\n `[${context.provider.getName()}] Discovery ${stepName} (groupIndex=${groupIndex})`;\n\n while (!context.stopped) {\n // Fast‑forward to current high‑water mark\n const targetGroupIndex = Math.max(context.groupIndex, maxGroupIndex);\n\n log(message('STARTED', targetGroupIndex));\n\n let accounts: Account[] = [];\n try {\n accounts = await context.provider.discoverAccounts({\n entropySource: this.#entropySource,\n groupIndex: targetGroupIndex,\n });\n } catch (error) {\n context.stopped = true;\n console.error(error);\n log(message('FAILED', targetGroupIndex), error);\n break;\n }\n\n if (!accounts.length) {\n log(message('STOPPED', targetGroupIndex));\n context.stopped = true;\n break;\n }\n\n log(message('SUCCEEDED', targetGroupIndex));\n\n context.accounts = context.accounts.concat(accounts);\n\n const nextGroupIndex = targetGroupIndex + 1;\n context.groupIndex = nextGroupIndex;\n\n if (nextGroupIndex > maxGroupIndex) {\n maxGroupIndex = nextGroupIndex;\n }\n }\n };\n\n const providerContexts: AccountProviderDiscoveryContext<Account>[] =\n this.#providers.map((provider) => ({\n provider,\n stopped: false,\n groupIndex: maxGroupIndex,\n accounts: [],\n }));\n\n // Start discovery for each providers.\n await Promise.all(providerContexts.map(runProviderDiscovery));\n\n // Sync the wallet after discovery to ensure that the newly added accounts are added into their groups.\n // We can potentially remove this if we know that this race condition is not an issue in practice.\n this.sync();\n\n // Align missing accounts from group. This is required to create missing account from non-discovered\n // indexes for some providers.\n await this.#alignAccounts();\n\n return providerContexts.flatMap((context) => context.accounts);\n });\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainAccountWallet.cjs","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getGroupIndexFromMultichainAccountGroupId,\n isMultichainAccountGroupId,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport { toDefaultAccountGroupId } from '@metamask/account-api';\nimport { AccountWalletType } from '@metamask/account-api';\nimport type {\n Bip44Account,\n MultichainAccountWalletId,\n MultichainAccountWallet as MultichainAccountWalletDefinition,\n MultichainAccountWalletStatus,\n} from '@metamask/account-api';\nimport type { AccountGroupId } from '@metamask/account-api';\nimport {\n type EntropySourceId,\n type KeyringAccount,\n} from '@metamask/keyring-api';\nimport { Mutex } from 'async-mutex';\n\nimport type { Logger } from './logger';\nimport {\n createModuleLogger,\n projectLogger as log,\n WARNING_PREFIX,\n} from './logger';\nimport { MultichainAccountGroup } from './MultichainAccountGroup';\nimport type { NamedAccountProvider } from './providers';\nimport type { MultichainAccountServiceMessenger } from './types';\n\n/**\n * The context for a provider discovery.\n */\ntype AccountProviderDiscoveryContext<\n Account extends Bip44Account<KeyringAccount>,\n> = {\n provider: NamedAccountProvider<Account>;\n stopped: boolean;\n groupIndex: number;\n accounts: Account[];\n};\n\n/**\n * A multichain account wallet that holds multiple multichain accounts (one multichain account per\n * group index).\n */\nexport class MultichainAccountWallet<\n Account extends Bip44Account<KeyringAccount>,\n> implements MultichainAccountWalletDefinition<Account>\n{\n readonly #lock = new Mutex();\n\n readonly #id: MultichainAccountWalletId;\n\n readonly #providers: NamedAccountProvider<Account>[];\n\n readonly #entropySource: EntropySourceId;\n\n readonly #accountGroups: Map<number, MultichainAccountGroup<Account>>;\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 #status: MultichainAccountWalletStatus;\n\n constructor({\n providers,\n entropySource,\n messenger,\n }: {\n providers: NamedAccountProvider<Account>[];\n entropySource: EntropySourceId;\n messenger: MultichainAccountServiceMessenger;\n }) {\n this.#id = toMultichainAccountWalletId(entropySource);\n this.#providers = providers;\n this.#entropySource = entropySource;\n this.#messenger = messenger;\n this.#accountGroups = new Map();\n\n this.#log = createModuleLogger(log, `[${this.#id}]`);\n\n // Initial synchronization (don't emit events during initialization).\n this.#status = 'uninitialized';\n this.sync();\n this.#initialized = true;\n this.#status = 'ready';\n }\n\n /**\n * Force wallet synchronization.\n *\n * This can be used if account providers got new accounts that the wallet\n * doesn't know about.\n */\n sync(): void {\n this.#log('Synchronizing with account providers...');\n for (const provider of this.#providers) {\n for (const account of provider.getAccounts()) {\n const { entropy } = account.options;\n\n // Filter for this wallet only.\n if (entropy.id !== this.entropySource) {\n continue;\n }\n\n // This multichain account might exists already.\n let multichainAccount = this.#accountGroups.get(entropy.groupIndex);\n if (!multichainAccount) {\n multichainAccount = new MultichainAccountGroup<Account>({\n groupIndex: entropy.groupIndex,\n wallet: this,\n providers: this.#providers,\n messenger: this.#messenger,\n });\n\n // This existing multichain account group might differ from the\n // `createMultichainAccountGroup` behavior. When creating a new\n // group, we expect the providers to all succeed. But here, we're\n // just fetching the account lists from them, so this group might\n // not be \"aligned\" yet (e.g having a missing Solana account).\n //\n // Since \"aligning\" is an async operation, it would have to be run\n // after the first-sync.\n // TODO: Implement align mechanism to create \"missing\" accounts.\n\n this.#log(`Found a new group: [${multichainAccount.id}]`);\n this.#accountGroups.set(entropy.groupIndex, multichainAccount);\n }\n }\n }\n\n // Now force-sync all remaining multichain accounts.\n for (const [\n groupIndex,\n multichainAccount,\n ] of this.#accountGroups.entries()) {\n multichainAccount.sync();\n\n // Clean up old multichain accounts.\n if (!multichainAccount.hasAccounts()) {\n this.#log(`Deleting group: [${multichainAccount.id}]`);\n this.#accountGroups.delete(groupIndex);\n }\n }\n\n this.#log('Synchronized');\n }\n\n /**\n * Gets the multichain account wallet ID.\n *\n * @returns The multichain account wallet ID.\n */\n get id(): MultichainAccountWalletId {\n return this.#id;\n }\n\n /**\n * Gets the multichain account wallet type, which is always {@link AccountWalletType.Entropy}.\n *\n * @returns The multichain account wallet type.\n */\n get type(): AccountWalletType.Entropy {\n return AccountWalletType.Entropy;\n }\n\n /**\n * Gets the multichain account wallet entropy source.\n *\n * @returns The multichain account wallet entropy source.\n */\n get entropySource(): EntropySourceId {\n return this.#entropySource;\n }\n\n /**\n * Gets the multichain account wallet current status.\n *\n * @returns The multichain account wallet current status.\n */\n get status(): MultichainAccountWalletStatus {\n return this.#status;\n }\n\n /**\n * Set the wallet status and run the associated operation callback.\n *\n * @param status - Wallet status associated with this operation.\n * @param operation - Operation to run.\n * @returns The operation's result.\n * @throws {Error} If the wallet is already running a mutable operation.\n */\n async #withLock<Return>(\n status: MultichainAccountWalletStatus,\n operation: () => Promise<Return>,\n ) {\n const release = await this.#lock.acquire();\n try {\n this.#log(`Locking wallet with status \"${status}\"...`);\n this.#status = status;\n this.#messenger.publish(\n 'MultichainAccountService:walletStatusChange',\n this.id,\n this.#status,\n );\n return await operation();\n } finally {\n this.#status = 'ready';\n this.#messenger.publish(\n 'MultichainAccountService:walletStatusChange',\n this.id,\n this.#status,\n );\n release();\n this.#log(`Releasing wallet lock (was \"${status}\")`);\n }\n }\n\n /**\n * Gets multichain account for a given ID.\n * The default group ID will default to the multichain account with index 0.\n *\n * @param id - Account group ID.\n * @returns Account group.\n */\n getAccountGroup(\n id: AccountGroupId,\n ): MultichainAccountGroup<Account> | undefined {\n // We consider the \"default case\" to be mapped to index 0.\n if (id === toDefaultAccountGroupId(this.id)) {\n return this.#accountGroups.get(0);\n }\n\n // If it is not a valid ID, we cannot extract the group index\n // from it, so we fail fast.\n if (!isMultichainAccountGroupId(id)) {\n return undefined;\n }\n\n const groupIndex = getGroupIndexFromMultichainAccountGroupId(id);\n return this.#accountGroups.get(groupIndex);\n }\n\n /**\n * Gets all multichain accounts. Similar to {@link MultichainAccountWallet.getMultichainAccountGroups}.\n *\n * @returns The multichain accounts.\n */\n getAccountGroups(): MultichainAccountGroup<Account>[] {\n return this.getMultichainAccountGroups();\n }\n\n /**\n * Gets multichain account group for a given index.\n *\n * @param groupIndex - Multichain account index.\n * @returns The multichain account associated with the given index.\n */\n getMultichainAccountGroup(\n groupIndex: number,\n ): MultichainAccountGroup<Account> | undefined {\n return this.#accountGroups.get(groupIndex);\n }\n\n /**\n * Gets all multichain account groups.\n *\n * @returns The multichain accounts.\n */\n getMultichainAccountGroups(): MultichainAccountGroup<Account>[] {\n return Array.from(this.#accountGroups.values()); // TODO: Prevent copy here.\n }\n\n /**\n * Gets next group index for this wallet.\n *\n * @returns The next group index of this wallet.\n */\n getNextGroupIndex(): number {\n // We do not check for gaps.\n return (\n Math.max(\n -1, // So it will default to 0 if no groups.\n ...this.#accountGroups.keys(),\n ) + 1\n );\n }\n\n /**\n * Creates a multichain account group for a given group index.\n *\n * NOTE: This operation WILL lock the wallet's mutex.\n *\n * @param groupIndex - The group index to use.\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for this group index.\n */\n async createMultichainAccountGroup(\n groupIndex: number,\n ): Promise<MultichainAccountGroup<Account>> {\n return await this.#withLock('in-progress:create-accounts', async () => {\n const nextGroupIndex = this.getNextGroupIndex();\n if (groupIndex > nextGroupIndex) {\n throw new Error(\n `You cannot use a group index that is higher than the next available one: expected <=${nextGroupIndex}, got ${groupIndex}`,\n );\n }\n\n let group = this.getMultichainAccountGroup(groupIndex);\n if (group) {\n // If the group already exists, we just `sync` it and returns the same\n // reference.\n group.sync();\n\n this.#log(\n `Trying to re-create existing group: [${group.id}] (idempotent)`,\n );\n return group;\n }\n\n this.#log(`Creating new group for index ${groupIndex}...`);\n const results = await Promise.allSettled(\n this.#providers.map((provider) =>\n provider.createAccounts({\n entropySource: this.#entropySource,\n groupIndex,\n }),\n ),\n );\n\n // --------------------------------------------------------------------------------\n // READ THIS CAREFULLY:\n //\n // Since we're not \"fully supporting multichain\" for now, we still rely on single\n // :accountCreated events to sync multichain account groups and wallets. Which means\n // that even if of the provider fails, some accounts will still be created on some\n // other providers and will become \"available\" on the `AccountsController`, like:\n //\n // 1. Creating a multichain account group for index 1\n // 2. EvmAccountProvider.createAccounts returns the EVM account for index 1\n // * AccountsController WILL fire :accountCreated for this account\n // * This account WILL BE \"available\" on the AccountsController state\n // 3. SolAccountProvider.createAccounts fails to create a Solana account for index 1\n // * AccountsController WON't fire :accountCreated for this account\n // * This account WON'T be \"available\" on the Account\n // 4. MultichainAccountService will receive a :accountCreated for the EVM account from\n // step 2 and will create a new multichain account group for index 1, but it won't\n // receive any event for the Solana account of this group. Thus, this group won't be\n // \"aligned\" (missing \"blockchain account\" on this group).\n //\n // --------------------------------------------------------------------------------\n\n // If any of the provider failed to create their accounts, then we consider the\n // multichain account group to have failed too.\n if (results.some((result) => result.status === 'rejected')) {\n // NOTE: Some accounts might still have been created on other account providers. We\n // don't rollback them.\n const error = `Unable to create multichain account group for index: ${groupIndex}`;\n\n let message = `${error}:`;\n for (const result of results) {\n if (result.status === 'rejected') {\n message += `\\n- ${result.reason}`;\n }\n }\n this.#log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n\n throw new Error(error);\n }\n\n // Because of the :accountAdded automatic sync, we might already have created the\n // group, so we first try to get it.\n group = this.getMultichainAccountGroup(groupIndex);\n if (!group) {\n // If for some reason it's still not created, we're creating it explicitly now:\n group = new MultichainAccountGroup({\n wallet: this,\n providers: this.#providers,\n groupIndex,\n messenger: this.#messenger,\n });\n }\n\n // Register the account to our internal map.\n this.#accountGroups.set(groupIndex, group); // `group` cannot be undefined here.\n this.#log(`New group created: [${group.id}]`);\n\n if (this.#initialized) {\n this.#messenger.publish(\n 'MultichainAccountService:multichainAccountGroupCreated',\n group,\n );\n }\n\n return group;\n });\n }\n\n /**\n * Creates the next multichain account group.\n *\n * @throws If any of the account providers fails to create their accounts.\n * @returns The multichain account group for the next group index available.\n */\n async createNextMultichainAccountGroup(): Promise<\n MultichainAccountGroup<Account>\n > {\n return this.createMultichainAccountGroup(this.getNextGroupIndex());\n }\n\n /**\n * Align all multichain account groups.\n *\n * NOTE: This operation WILL NOT lock the wallet's mutex.\n */\n async #alignAccounts(): Promise<void> {\n const groups = this.getMultichainAccountGroups();\n await Promise.all(groups.map((group) => group.alignAccounts()));\n }\n\n /**\n * Align all accounts from each existing multichain account groups.\n *\n * NOTE: This operation WILL lock the wallet's mutex.\n */\n async alignAccounts(): Promise<void> {\n await this.#withLock('in-progress:alignment', async () => {\n await this.#alignAccounts();\n });\n }\n\n /**\n * Align a specific multichain account group.\n *\n * NOTE: This operation WILL lock the wallet's mutex.\n *\n * @param groupIndex - The group index to align.\n */\n async alignAccountsOf(groupIndex: number): Promise<void> {\n await this.#withLock('in-progress:alignment', async () => {\n const group = this.getMultichainAccountGroup(groupIndex);\n if (group) {\n await group.alignAccounts();\n }\n });\n }\n\n /**\n * Discover and create accounts for all providers.\n *\n * NOTE: This operation WILL lock the wallet's mutex.\n *\n * @returns The discovered accounts for each provider.\n */\n async discoverAccounts(): Promise<Account[]> {\n return this.#withLock('in-progress:discovery', async () => {\n // Start with the next available group index (so we can resume the discovery\n // from there).\n let maxGroupIndex = this.getNextGroupIndex();\n\n // One serialized loop per provider; all run concurrently\n const runProviderDiscovery = async (\n context: AccountProviderDiscoveryContext<Account>,\n ) => {\n const providerName = context.provider.getName();\n const message = (stepName: string, groupIndex: number) =>\n `[${providerName}] Discovery ${stepName} for group index: ${groupIndex}`;\n\n while (!context.stopped) {\n // Fast‑forward to current high‑water mark\n const targetGroupIndex = Math.max(context.groupIndex, maxGroupIndex);\n\n log(message('started', targetGroupIndex));\n\n let accounts: Account[] = [];\n try {\n accounts = await context.provider.discoverAccounts({\n entropySource: this.#entropySource,\n groupIndex: targetGroupIndex,\n });\n } catch (error) {\n context.stopped = true;\n console.error(error);\n log(\n message(\n `failed (with: \"${(error as Error).message}\")`,\n targetGroupIndex,\n ),\n error,\n );\n break;\n }\n\n if (!accounts.length) {\n log(\n message('stopped (no accounts got discovered)', targetGroupIndex),\n );\n context.stopped = true;\n break;\n }\n\n log(message('**succeeded**', targetGroupIndex));\n\n context.accounts = context.accounts.concat(accounts);\n\n const nextGroupIndex = targetGroupIndex + 1;\n context.groupIndex = nextGroupIndex;\n\n if (nextGroupIndex > maxGroupIndex) {\n maxGroupIndex = nextGroupIndex;\n }\n }\n };\n\n const providerContexts: AccountProviderDiscoveryContext<Account>[] =\n this.#providers.map((provider) => ({\n provider,\n stopped: false,\n groupIndex: maxGroupIndex,\n accounts: [],\n }));\n\n // Start discovery for each providers.\n await Promise.all(providerContexts.map(runProviderDiscovery));\n\n // Sync the wallet after discovery to ensure that the newly added accounts are added into their groups.\n // We can potentially remove this if we know that this race condition is not an issue in practice.\n this.sync();\n\n // Align missing accounts from group. This is required to create missing account from non-discovered\n // indexes for some providers.\n await this.#alignAccounts();\n\n return providerContexts.flatMap((context) => context.accounts);\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountWallet.d.cts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC5D,6BAA6B,EAC9B,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAI/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAAoB;AACxD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAgBjE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAmBzC,EACV,SAAS,EACT,aAAa,EACb,SAAS,GACV,EAAE;QACD,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,aAAa,EAAE,eAAe,CAAC;QAC/B,SAAS,EAAE,iCAAiC,CAAC;KAC9C;IAcD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAiDZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,6BAA6B,CAE1C;IAkCD;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAI/D;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAU3B;;;;;;;;OAQG;IACG,4BAA4B,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IA8F3C;;;;;OAKG;IACG,gCAAgC,IAAI,OAAO,CAC/C,sBAAsB,CAAC,OAAO,CAAC,CAChC;IAcD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAMpC;;;;;;OAMG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxD;;;;;;OAMG;IACG,gBAAgB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;CAyE7C"}
1
+ {"version":3,"file":"MultichainAccountWallet.d.cts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC5D,6BAA6B,EAC9B,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAS/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAAoB;AACxD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAcjE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAqBzC,EACV,SAAS,EACT,aAAa,EACb,SAAS,GACV,EAAE;QACD,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,aAAa,EAAE,eAAe,CAAC;QAC/B,SAAS,EAAE,iCAAiC,CAAC;KAC9C;IAgBD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAsDZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,6BAA6B,CAE1C;IAoCD;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAI/D;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAU3B;;;;;;;;OAQG;IACG,4BAA4B,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAoG3C;;;;;OAKG;IACG,gCAAgC,IAAI,OAAO,CAC/C,sBAAsB,CAAC,OAAO,CAAC,CAChC;IAcD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAMpC;;;;;;OAMG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxD;;;;;;OAMG;IACG,gBAAgB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;CAkF7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAccountWallet.d.mts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC5D,6BAA6B,EAC9B,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAI/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAAoB;AACxD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAgBjE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAmBzC,EACV,SAAS,EACT,aAAa,EACb,SAAS,GACV,EAAE;QACD,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,aAAa,EAAE,eAAe,CAAC;QAC/B,SAAS,EAAE,iCAAiC,CAAC;KAC9C;IAcD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAiDZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,6BAA6B,CAE1C;IAkCD;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAI/D;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAU3B;;;;;;;;OAQG;IACG,4BAA4B,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IA8F3C;;;;;OAKG;IACG,gCAAgC,IAAI,OAAO,CAC/C,sBAAsB,CAAC,OAAO,CAAC,CAChC;IAcD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAMpC;;;;;;OAMG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxD;;;;;;OAMG;IACG,gBAAgB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;CAyE7C"}
1
+ {"version":3,"file":"MultichainAccountWallet.d.mts","sourceRoot":"","sources":["../src/MultichainAccountWallet.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,uBAAuB,IAAI,iCAAiC,EAC5D,6BAA6B,EAC9B,8BAA8B;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,8BAA8B;AAS/B,OAAO,EAAE,sBAAsB,EAAE,qCAAiC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAAoB;AACxD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAcjE;;;GAGG;AACH,qBAAa,uBAAuB,CAClC,OAAO,SAAS,YAAY,CAAC,cAAc,CAAC,CAC5C,YAAW,iCAAiC,CAAC,OAAO,CAAC;;gBAqBzC,EACV,SAAS,EACT,aAAa,EACb,SAAS,GACV,EAAE;QACD,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,aAAa,EAAE,eAAe,CAAC;QAC/B,SAAS,EAAE,iCAAiC,CAAC;KAC9C;IAgBD;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAsDZ;;;;OAIG;IACH,IAAI,EAAE,IAAI,yBAAyB,CAElC;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,iBAAiB,CAAC,OAAO,CAEpC;IAED;;;;OAIG;IACH,IAAI,aAAa,IAAI,eAAe,CAEnC;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI,6BAA6B,CAE1C;IAoCD;;;;;;OAMG;IACH,eAAe,CACb,EAAE,EAAE,cAAc,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAgB9C;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAIrD;;;;;OAKG;IACH,yBAAyB,CACvB,UAAU,EAAE,MAAM,GACjB,sBAAsB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI9C;;;;OAIG;IACH,0BAA0B,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAI/D;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAU3B;;;;;;;;OAQG;IACG,4BAA4B,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAoG3C;;;;;OAKG;IACG,gCAAgC,IAAI,OAAO,CAC/C,sBAAsB,CAAC,OAAO,CAAC,CAChC;IAcD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAMpC;;;;;;OAMG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxD;;;;;;OAMG;IACG,gBAAgB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;CAkF7C"}