{"version":3,"file":"MultichainAccountGroup.cjs","sourceRoot":"","sources":["../src/MultichainAccountGroup.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountGroupType, select, selectOne } from '@metamask/account-api';\nimport { toMultichainAccountGroupId } from '@metamask/account-api';\nimport type {\n  MultichainAccountGroupId,\n  MultichainAccountGroup as MultichainAccountGroupDefinition,\n} from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { AccountSelector } from '@metamask/account-api';\nimport type { KeyringAccount } from '@metamask/keyring-api';\n\nimport type { Logger } from './logger';\nimport { projectLogger as log, createModuleLogger } from './logger';\nimport type { ServiceState, StateKeys } from './MultichainAccountService';\nimport type { MultichainAccountWallet } from './MultichainAccountWallet';\nimport type { Bip44AccountProvider } from './providers';\nimport type { MultichainAccountServiceMessenger } from './types';\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  readonly #id: MultichainAccountGroupId;\n\n  readonly #wallet: MultichainAccountWallet<Account>;\n\n  readonly #groupIndex: number;\n\n  readonly #providers: Bip44AccountProvider<Account>[];\n\n  readonly #providerToAccounts: Map<\n    Bip44AccountProvider<Account>,\n    Account['id'][]\n  >;\n\n  readonly #accountToProvider: Map<\n    Account['id'],\n    Bip44AccountProvider<Account>\n  >;\n\n  readonly #messenger: MultichainAccountServiceMessenger;\n\n  readonly #log: Logger;\n\n  #initialized = false;\n\n  constructor({\n    groupIndex,\n    wallet,\n    providers,\n    messenger,\n  }: {\n    groupIndex: number;\n    wallet: MultichainAccountWallet<Account>;\n    providers: Bip44AccountProvider<Account>[];\n    messenger: MultichainAccountServiceMessenger;\n  }) {\n    this.#id = toMultichainAccountGroupId(wallet.id, groupIndex);\n    this.#groupIndex = groupIndex;\n    this.#wallet = wallet;\n    this.#providers = providers;\n    this.#messenger = messenger;\n    this.#providerToAccounts = new Map();\n    this.#accountToProvider = new Map();\n\n    this.#log = createModuleLogger(log, `[${this.#id}]`);\n  }\n\n  /**\n   * Clear the account to provider state for a given provider.\n   *\n   * @param provider - The provider to clear the account to provider state for.\n   */\n  #clearAccountToProviderState(provider: Bip44AccountProvider<Account>): void {\n    this.#accountToProvider.forEach((accountProvider, id) => {\n      if (accountProvider === provider) {\n        this.#accountToProvider.delete(id);\n      }\n    });\n  }\n\n  /**\n   * Update the internal representation of accounts with the given group state.\n   *\n   * @param groupState - The group state.\n   */\n  #setState(groupState: GroupState): void {\n    for (const provider of this.#providers) {\n      const accountIds = groupState[provider.getName()];\n\n      if (accountIds) {\n        this.#clearAccountToProviderState(provider);\n        this.#providerToAccounts.set(provider, accountIds);\n\n        for (const accountId of accountIds) {\n          this.#accountToProvider.set(accountId, provider);\n        }\n      }\n    }\n  }\n\n  /**\n   * Initialize the multichain account group and construct the internal representation of accounts.\n   *\n   * @param groupState - The group state.\n   */\n  init(groupState: GroupState): void {\n    this.#log('Initializing group state...');\n    this.#setState(groupState);\n    this.#log('Finished initializing group state...');\n\n    this.#initialized = true;\n  }\n\n  /**\n   * Update the group state.\n   *\n   * @param groupState - The group state.\n   */\n  update(groupState: GroupState): void {\n    this.#log('Updating group state...');\n    this.#setState(groupState);\n    this.#log('Finished updating group state...');\n\n    if (this.#initialized) {\n      this.#messenger.publish(\n        'MultichainAccountService:multichainAccountGroupUpdated',\n        this,\n      );\n    }\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   * Check whether every provider has an aligned account in this group.\n   *\n   * A group is aligned when every registered provider reports that the\n   * account IDs it contributed to this group are non-empty and owned by it.\n   * Disabled {@link AccountProviderWrapper} instances always report `true`.\n   *\n   * @returns `true` when all providers are aligned for this group.\n   */\n  isAligned(): boolean {\n    return this.#providers.every((provider) =>\n      this.isProviderAligned(provider),\n    );\n  }\n\n  /**\n   * Check whether a single provider has an aligned account in this group.\n   *\n   * A provider is aligned when the account IDs it contributed to this group are\n   * non-empty and owned by it. Disabled {@link AccountProviderWrapper} instances\n   * always report `true`.\n   *\n   * @param provider - The provider to check.\n   * @returns `true` when the provider is aligned for this group.\n   */\n  isProviderAligned(provider: Bip44AccountProvider<Account>): boolean {\n    return provider.isAligned(\n      {\n        entropySource: this.#wallet.entropySource,\n        groupIndex: this.#groupIndex,\n      },\n      this.#providerToAccounts.get(provider) ?? [],\n    );\n  }\n}\n"]}