UNPKG

@metamask/multichain-account-service

Version:
1 lines 12.3 kB
{"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"]}