{"version":3,"file":"group.cjs","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":";;;AAMA,uDAO+B;AAqBlB,QAAA,cAAc,GAAG,IAAI,CAAC;AAEnC;;GAEG;AACU,QAAA,0BAA0B,GAAuC;IAC5E,CAAC,4BAAc,CAAC,GAAG,CAAC,EAAE,CAAC;IACvB,CAAC,4BAAc,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3B,CAAC,4BAAc,CAAC,WAAW,CAAC,EAAE,CAAC;IAC/B,CAAC,4BAAc,CAAC,KAAK,CAAC,EAAE,CAAC;IACzB,CAAC,4BAAc,CAAC,IAAI,CAAC,EAAE,CAAC;IACxB,CAAC,4BAAc,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,CAAC,4BAAc,CAAC,IAAI,CAAC,EAAE,CAAC;IACxB,CAAC,4BAAc,CAAC,GAAG,CAAC,EAAE,CAAC;IACvB,CAAC,4BAAc,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3B,CAAC,4BAAc,CAAC,OAAO,CAAC,EAAE,sBAAc;CACzC,CAAC;AAsEF;;;;;;;GAOG;AACH,SAAgB,kCAAkC,CAChD,MAA2B,EAC3B,OAAuB,EACvB,IAAY;IAEZ,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAEhC,0CAA0C;IAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,CAAC,EAAE,KAAK,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,WAAW,EAAE,CAAC;YACvE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAdD,gFAcC;AAED;;;;;;;;GAQG;AACH,SAAgB,wBAAwB,CACtC,KAAiC,EACjC,OAAuB,EACvB,IAAY;IAEZ,0DAA0D;IAC1D,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,mDAAmD;YACnD,OAAO,kCAAkC,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;AACrD,CAAC;AAdD,4DAcC","sourcesContent":["import type {\n  AccountGroupType,\n  MultichainAccountGroupId,\n} from '@metamask/account-api';\nimport type { AccountGroupId } from '@metamask/account-api';\nimport type { AccountId } from '@metamask/accounts-controller';\nimport {\n  AnyAccountType,\n  BtcAccountType,\n  EthAccountType,\n  SolAccountType,\n  TrxAccountType,\n  XlmAccountType,\n} from '@metamask/keyring-api';\nimport type { KeyringAccountType } from '@metamask/keyring-api';\n\nimport type { UpdatableField, ExtractFieldValues } from './type-utils';\nimport type { AccountTreeControllerState } from './types';\nimport type { AccountWalletObject } from './wallet';\n\n/**\n * Persisted metadata for account groups (stored in controller state for persistence/sync).\n */\nexport type AccountTreeGroupPersistedMetadata = {\n  /** Custom name set by user, overrides default naming logic */\n  name?: UpdatableField<string>;\n  /** Whether this group is pinned in the UI */\n  pinned?: UpdatableField<boolean>;\n  /** Whether this group is hidden in the UI */\n  hidden?: UpdatableField<boolean>;\n  /** Timestamp of the last time this group was selected (local-only, not synced) */\n  lastSelected?: number;\n};\n\nexport const MAX_SORT_ORDER = 9999;\n\n/**\n * Order of account types.\n */\nexport const ACCOUNT_TYPE_TO_SORT_ORDER: Record<KeyringAccountType, number> = {\n  [EthAccountType.Eoa]: 0,\n  [EthAccountType.Erc4337]: 1,\n  [SolAccountType.DataAccount]: 2,\n  [BtcAccountType.P2pkh]: 3,\n  [BtcAccountType.P2sh]: 4,\n  [BtcAccountType.P2wpkh]: 5,\n  [BtcAccountType.P2tr]: 6,\n  [TrxAccountType.Eoa]: 7,\n  [XlmAccountType.Account]: 8,\n  [AnyAccountType.Account]: MAX_SORT_ORDER,\n};\n\nexport type AccountTypeOrderKey = keyof typeof ACCOUNT_TYPE_TO_SORT_ORDER;\n\n/**\n * Tree metadata for account groups (required plain values extracted from persisted metadata).\n */\nexport type AccountTreeGroupMetadata = Required<\n  ExtractFieldValues<AccountTreeGroupPersistedMetadata>\n>;\n\n/**\n * Type constraint for a {@link AccountGroupObject}. If one of its union-members\n * does not match this contraint, {@link AccountGroupObject} will resolve\n * to `never`.\n */\ntype IsAccountGroupObject<\n  Type extends {\n    type: AccountGroupType;\n    id: AccountGroupId;\n    accounts: AccountId[];\n    metadata: AccountTreeGroupMetadata;\n  },\n> = Type;\n\n/**\n * Multichain-account group object.\n */\nexport type AccountGroupMultichainAccountObject = {\n  type: AccountGroupType.MultichainAccount;\n  id: MultichainAccountGroupId;\n  // Blockchain Accounts (at least 1 account per multichain-accounts):\n  accounts: [AccountId, ...AccountId[]];\n  metadata: AccountTreeGroupMetadata & {\n    entropy: {\n      groupIndex: number;\n    };\n  };\n};\n\n/**\n * Multichain-account group object.\n */\nexport type AccountGroupSingleAccountObject = {\n  type: AccountGroupType.SingleAccount;\n  id: AccountGroupId;\n  // Blockchain Accounts (1 account per group):\n  accounts: [AccountId];\n  metadata: AccountTreeGroupMetadata;\n};\n\n/**\n * Account group object.\n */\nexport type AccountGroupObject = IsAccountGroupObject<\n  AccountGroupMultichainAccountObject | AccountGroupSingleAccountObject\n>;\n\nexport type AccountGroupObjectOf<GroupType extends AccountGroupType> = Extract<\n  | {\n      type: AccountGroupType.MultichainAccount;\n      object: AccountGroupMultichainAccountObject;\n    }\n  | {\n      type: AccountGroupType.SingleAccount;\n      object: AccountGroupSingleAccountObject;\n    },\n  { type: GroupType }\n>['object'];\n\n/**\n * Checks if a group name is unique within a specific wallet.\n *\n * @param wallet - The wallet to check within.\n * @param groupId - The account group ID to exclude from the check.\n * @param name - The name to validate for uniqueness.\n * @returns True if the name is unique within the wallet, false otherwise.\n */\nexport function isAccountGroupNameUniqueFromWallet(\n  wallet: AccountWalletObject,\n  groupId: AccountGroupId,\n  name: string,\n): boolean {\n  const trimmedName = name.trim();\n\n  // Check for duplicates within this wallet\n  for (const group of Object.values(wallet.groups)) {\n    if (group.id !== groupId && group.metadata.name.trim() === trimmedName) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Checks if an account group name is unique within the same wallet.\n *\n * @param state - The account tree controller state.\n * @param groupId - The account group ID to exclude from the check.\n * @param name - The name to validate for uniqueness.\n * @returns True if the name is unique within the same wallet, false otherwise.\n * @throws Error if the group ID does not exist.\n */\nexport function isAccountGroupNameUnique(\n  state: AccountTreeControllerState,\n  groupId: AccountGroupId,\n  name: string,\n): boolean {\n  // Find the wallet that contains the group being validated\n  for (const wallet of Object.values(state.accountTree.wallets)) {\n    if (wallet.groups[groupId]) {\n      // Use the wallet-specific function for consistency\n      return isAccountGroupNameUniqueFromWallet(wallet, groupId, name);\n    }\n  }\n\n  throw new Error('Account group not found in tree');\n}\n"]}