@metamask-previews/account-tree-controller 7.1.0-preview-a89313ea9 → 7.1.0-preview-dccbcec3e

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.
@@ -22,9 +22,6 @@ const metadata_1 = require("./metadata.cjs");
22
22
  * @returns Array of created group IDs.
23
23
  */
24
24
  const createMultichainAccountGroupsBatch = async (context, entropySourceId, maxGroupIndex, profileId, analyticsAction) => {
25
- console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Creating ${maxGroupIndex + 1} account groups (batch) for entropy source: ${entropySourceId}`);
26
- console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Max group index: ${maxGroupIndex}`);
27
- console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Context: ${JSON.stringify(context)}`);
28
25
  const numberOfAccountGroupsToCreate = maxGroupIndex + 1; // maxGroupIndex is zero-based, so we add 1 to get the count.
29
26
  (0, logger_1.backupAndSyncLogger)(`Creating ${numberOfAccountGroupsToCreate} account groups (batch) for entropy source: ${entropySourceId}`);
30
27
  // Capture the set of group indices that already exist before the batch call,
@@ -1 +1 @@
1
- {"version":3,"file":"group.cjs","sourceRoot":"","sources":["../../../src/backup-and-sync/syncing/group.ts"],"names":[],"mappings":";;;AAAA,uDAAoE;AAGpE,6CAAmD;AAGnD,sDAA2D;AAE3D,wCAA8D;AAK9D,+EAG4C;AAC5C,8CAA0D;AAC1D,gDAAiD;AACjD,6CAAoD;AAEpD;;;;;;;;;;;GAWG;AACI,MAAM,kCAAkC,GAAG,KAAK,EACrD,OAA6B,EAC7B,eAAuB,EACvB,aAAqB,EACrB,SAAoB,EACpB,eAA6C,EAC9B,EAAE;IACjB,OAAO,CAAC,GAAG,CAAC,qEAAqE,aAAa,GAAG,CAAC,+CAA+C,eAAe,EAAE,CAAC,CAAC;IACpK,OAAO,CAAC,GAAG,CAAC,6EAA6E,aAAa,EAAE,CAAC,CAAC;IAC1G,OAAO,CAAC,GAAG,CAAC,qEAAqE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAE5G,MAAM,6BAA6B,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,6DAA6D;IACtH,IAAA,4BAAmB,EACjB,YAAY,6BAA6B,+CAA+C,eAAe,EAAE,CAC1G,CAAC;IAEF,6EAA6E;IAC7E,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,IAAA,yCAA2B,EAAC,eAAe,CAAC,CAAC;IAC9D,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAClC,IAAA,sCAA8B,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,GAAG,CACnD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAC7C,CACF,CAAC;IAEF,IAAI,CAAC;QACH,yDAAyD;QACzD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,CACzC,wDAAwD,EACxD;YACE,aAAa,EAAE,eAAe;YAC9B,cAAc,EAAE,CAAC;YACjB,YAAY,EAAE,aAAa;SAC5B,CACF,CAAC;QAEF,kDAAkD;QAClD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,kHAAkH;YAClH,uDAAuD;YACvD,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,oBAAoB,GAAG,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAExE,IAAI,CAAC,oBAAoB,EAAE,CAAC;oBAC1B,OAAO,CAAC,oBAAoB,CAAC;wBAC3B,MAAM,EAAE,eAAe;wBACvB,SAAS;qBACV,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAA,4BAAmB,EAAC,wBAAwB,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,qEAAqE;QACrE,4DAA4D;QAC5D,yEAAyE;QACzE,oFAAoF;QACpF,oCAAoC;QACpC,gEAAgE;QAEhE,IAAA,4BAAmB,EACjB,wCAAwC;QACxC,uBAAuB;QACvB,IAAA,uBAAc,EAAC,KAAK,CAAC,CACtB,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAnEW,QAAA,kCAAkC,sCAmE7C;AAEF;;;;;;;GAOG;AACI,KAAK,UAAU,gCAAgC,CACpD,OAA6B,EAC7B,qBAAqD,EACrD,eAAuB,EACvB,SAAoB;IAEpB,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAC5B,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAC1D,CAAC;IAEF,oEAAoE;IACpE,0CAA0C;IAC1C,6CAA6C;IAC7C,MAAM,IAAA,0CAAkC,EACtC,OAAO,EACP,eAAe,EACf,aAAa,EACb,SAAS,EACT,uCAA2B,CAAC,UAAU,CACvC,CAAC;AACJ,CAAC;AApBD,4EAoBC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,qCAAqC,CAClD,OAA6B,EAC7B,UAA+C,EAC/C,oBAAqE,EACrE,SAAoB;IAEpB,MAAM,sBAAsB,GAC1B,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,qBAAqB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAEhE,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,IAAA,4BAAmB,EACjB,SAAS,UAAU,CAAC,EAAE,4DAA4D,CACnF,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sDAAsD;IACtD,IAAI,eAAe,GAAG,KAAK,CAAC;IAE5B,iCAAiC;IACjC,MAAM,iBAAiB,GAAG,MAAM,IAAA,iCAAsB,EAAC;QACrD,OAAO;QACP,aAAa,EAAE,sBAAsB,EAAE,IAAI;QAC3C,mBAAmB,EAAE,oBAAoB,CAAC,IAAI;QAC9C,wBAAwB,EAAE,CAAC,KAAK,EAAE,EAAE,CAClC,0CAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;QACvE,gBAAgB,EAAE,CAAC,IAAY,EAAE,EAAE;YACjC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACpE,CAAC;QACD,SAAS,EAAE;YACT,MAAM,EAAE,uCAA2B,CAAC,YAAY;YAChD,SAAS;SACV;KACF,CAAC,CAAC;IAEH,eAAe,KAAf,eAAe,GAAK,iBAAiB,EAAC;IAEtC,mCAAmC;IACnC,MAAM,mBAAmB,GAAG,MAAM,IAAA,iCAAsB,EAAC;QACvD,OAAO;QACP,aAAa,EAAE,sBAAsB,EAAE,MAAM;QAC7C,mBAAmB,EAAE,oBAAoB,CAAC,MAAM;QAChD,wBAAwB,EAAE,CAAC,KAAK,EAAE,EAAE,CAClC,0CAAkC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;QACzE,gBAAgB,EAAE,CAAC,MAAe,EAAE,EAAE;YACpC,OAAO,CAAC,UAAU,CAAC,qBAAqB,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAClE,CAAC;QACD,SAAS,EAAE;YACT,MAAM,EAAE,uCAA2B,CAAC,wBAAwB;YAC5D,SAAS;SACV;KACF,CAAC,CAAC;IAEH,eAAe,KAAf,eAAe,GAAK,mBAAmB,EAAC;IAExC,mCAAmC;IACnC,MAAM,mBAAmB,GAAG,MAAM,IAAA,iCAAsB,EAAC;QACvD,OAAO;QACP,aAAa,EAAE,sBAAsB,EAAE,MAAM;QAC7C,mBAAmB,EAAE,oBAAoB,CAAC,MAAM;QAChD,wBAAwB,EAAE,CAAC,KAAK,EAAE,EAAE,CAClC,0CAAkC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;QACzE,gBAAgB,EAAE,CAAC,MAAe,EAAE,EAAE;YACpC,OAAO,CAAC,UAAU,CAAC,qBAAqB,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAClE,CAAC;QACD,SAAS,EAAE;YACT,MAAM,EAAE,uCAA2B,CAAC,wBAAwB;YAC5D,SAAS;SACV;KACF,CAAC,CAAC;IAEH,eAAe,KAAf,eAAe,GAAK,mBAAmB,EAAC;IAExC,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,iBAAiB,CACrC,OAA6B,EAC7B,UAA+C,EAC/C,oBAAyD,EACzD,eAAuB,EACvB,SAAoB;IAEpB,MAAM,eAAe,GAAG,MAAM,qCAAqC,CACjE,OAAO,EACP,UAAU,EACV,oBAAoB,EACpB,SAAS,CACV,CAAC;IAEF,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,IAAA,2CAAsB,EAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAjBD,8CAiBC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,kBAAkB,CACtC,OAA6B,EAC7B,MAAkC,EAClC,qBAAqD,EACrD,eAAuB,EACvB,SAAoB;IAEpB,MAAM,0CAA0C,GAC9C,EAAE,CAAC;IAEL,MAAM,mBAAmB,GAAG,IAAA,sCAA8B,EACxD,OAAO,EACP,MAAM,CAAC,EAAE,CACV,CAAC;IAEF,KAAK,MAAM,kBAAkB,IAAI,mBAAmB,EAAE,CAAC;QACrD,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,IAAI,CACrD,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,UAAU,KAAK,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CACtE,CAAC;QAEF,MAAM,eAAe,GAAG,MAAM,qCAAqC,CACjE,OAAO,EACP,kBAAkB,EAClB,oBAAoB,EACpB,SAAS,CACV,CAAC;QAEF,uEAAuE;QACvE,IAAI,eAAe,EAAE,CAAC;YACpB,0CAA0C,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,IAAI,0CAA0C,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAA,gDAA2B,EAC/B,OAAO,EACP,0CAA0C,EAC1C,eAAe,CAChB,CAAC;IACJ,CAAC;AACH,CAAC;AA1CD,gDA0CC","sourcesContent":["import { toMultichainAccountWalletId } from '@metamask/account-api';\n\nimport type { AccountGroupMultichainAccountObject } from '../../group';\nimport { backupAndSyncLogger } from '../../logger';\nimport type { AccountWalletEntropyObject } from '../../wallet';\nimport type { BackupAndSyncAnalyticsAction } from '../analytics';\nimport { BackupAndSyncAnalyticsEvent } from '../analytics';\nimport type { ProfileId } from '../authentication';\nimport { UserStorageSyncedWalletGroupSchema } from '../types';\nimport type {\n BackupAndSyncContext,\n UserStorageSyncedWalletGroup,\n} from '../types';\nimport {\n pushGroupToUserStorage,\n pushGroupToUserStorageBatch,\n} from '../user-storage/network-operations';\nimport { getLocalGroupsForEntropyWallet } from '../utils';\nimport { toErrorMessage } from '../utils/errors';\nimport { compareAndSyncMetadata } from './metadata';\n\n/**\n * Creates multiple multichain account groups in batch (from 0 to maxGroupIndex).\n * This is an optimized version that creates all groups in one operation instead of\n * creating them sequentially.\n *\n * @param context - The sync context containing controller and messenger.\n * @param entropySourceId - The entropy source ID.\n * @param maxGroupIndex - Number of account groups to create in batch.\n * @param profileId - The profile ID for analytics.\n * @param analyticsAction - The analytics action to log for each created group.\n * @returns Array of created group IDs.\n */\nexport const createMultichainAccountGroupsBatch = async (\n context: BackupAndSyncContext,\n entropySourceId: string,\n maxGroupIndex: number,\n profileId: ProfileId,\n analyticsAction: BackupAndSyncAnalyticsAction,\n): Promise<void> => {\n console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Creating ${maxGroupIndex + 1} account groups (batch) for entropy source: ${entropySourceId}`);\n console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Max group index: ${maxGroupIndex}`);\n console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Context: ${JSON.stringify(context)}`);\n\n const numberOfAccountGroupsToCreate = maxGroupIndex + 1; // maxGroupIndex is zero-based, so we add 1 to get the count.\n backupAndSyncLogger(\n `Creating ${numberOfAccountGroupsToCreate} account groups (batch) for entropy source: ${entropySourceId}`,\n );\n\n // Capture the set of group indices that already exist before the batch call,\n // so we can correctly identify newly created groups after the call completes.\n const walletId = toMultichainAccountWalletId(entropySourceId);\n const existingGroupIndices = new Set(\n getLocalGroupsForEntropyWallet(context, walletId).map(\n (group) => group.metadata.entropy.groupIndex,\n ),\n );\n\n try {\n // Call the batched creation method (this is idempotent).\n const groups = await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountGroups',\n {\n entropySource: entropySourceId,\n fromGroupIndex: 0,\n toGroupIndex: maxGroupIndex,\n },\n );\n\n // Contains all groups (existing + newly created).\n for (const group of groups) {\n // TODO: A group should not be null here, but EVM provider might fail to create some groups sometimes, which means\n // we can end up having an \"empty group\" for some time.\n if (group) {\n const didGroupAlreadyExist = existingGroupIndices.has(group.groupIndex);\n\n if (!didGroupAlreadyExist) {\n context.emitAnalyticsEventFn({\n action: analyticsAction,\n profileId,\n });\n }\n }\n }\n\n backupAndSyncLogger(`Successfully created ${groups.length} groups (batch)`);\n } catch (error) {\n // This can happen if the Snap Keyring is not ready yet when invoking\n // `MultichainAccountService:createMultichainAccountGroups`.\n // Since `MultichainAccountService:createMultichainAccountGroups` will at\n // least create the EVM account and the account group before throwing, we can safely\n // ignore this error and swallow it.\n // Any missing Snap accounts will be added later with alignment.\n\n backupAndSyncLogger(\n `Failed to create account groups batch:`,\n // istanbul ignore next\n toErrorMessage(error),\n );\n }\n};\n\n/**\n * Creates local groups from user storage groups.\n *\n * @param context - The sync context containing controller and messenger.\n * @param groupsFromUserStorage - Array of groups from user storage.\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function createLocalGroupsFromUserStorage(\n context: BackupAndSyncContext,\n groupsFromUserStorage: UserStorageSyncedWalletGroup[],\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const maxGroupIndex = Math.max(\n ...groupsFromUserStorage.map((group) => group.groupIndex),\n );\n\n // Creating multichain account group is idempotent, so we can safely\n // re-create every groups starting from 0.\n // Use batch creation for better performance.\n await createMultichainAccountGroupsBatch(\n context,\n entropySourceId,\n maxGroupIndex,\n profileId,\n BackupAndSyncAnalyticsEvent.GroupAdded,\n );\n}\n\n/**\n * Syncs group metadata fields and determines if the group needs to be pushed to user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param localGroup - The local group to sync.\n * @param groupFromUserStorage - The group from user storage to compare against.\n * @param profileId - The profile ID for analytics.\n * @returns A promise that resolves to true if the group needs to be pushed to user storage.\n */\nasync function syncGroupMetadataAndCheckIfPushNeeded(\n context: BackupAndSyncContext,\n localGroup: AccountGroupMultichainAccountObject,\n groupFromUserStorage: UserStorageSyncedWalletGroup | null | undefined,\n profileId: ProfileId,\n): Promise<boolean> {\n const groupPersistedMetadata =\n context.controller.state.accountGroupsMetadata[localGroup.id];\n\n if (!groupFromUserStorage) {\n backupAndSyncLogger(\n `Group ${localGroup.id} did not exist in user storage, pushing to user storage...`,\n );\n\n return true;\n }\n\n // Track if we need to push this group to user storage\n let shouldPushGroup = false;\n\n // Compare and sync name metadata\n const shouldPushForName = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.name,\n userStorageMetadata: groupFromUserStorage.name,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.name.schema.value.is(value),\n applyLocalUpdate: (name: string) => {\n context.controller.setAccountGroupName(localGroup.id, name, true);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupRenamed,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForName;\n\n // Compare and sync pinned metadata\n const shouldPushForPinned = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.pinned,\n userStorageMetadata: groupFromUserStorage.pinned,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.pinned.schema.value.is(value),\n applyLocalUpdate: (pinned: boolean) => {\n context.controller.setAccountGroupPinned(localGroup.id, pinned);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupPinnedStatusChanged,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForPinned;\n\n // Compare and sync hidden metadata\n const shouldPushForHidden = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.hidden,\n userStorageMetadata: groupFromUserStorage.hidden,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.hidden.schema.value.is(value),\n applyLocalUpdate: (hidden: boolean) => {\n context.controller.setAccountGroupHidden(localGroup.id, hidden);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupHiddenStatusChanged,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForHidden;\n\n return shouldPushGroup;\n}\n\n/**\n * Syncs a single group's metadata between local and user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param localGroup - The local group to sync.\n * @param groupFromUserStorage - The group from user storage to compare against (or null if it doesn't exist).\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function syncGroupMetadata(\n context: BackupAndSyncContext,\n localGroup: AccountGroupMultichainAccountObject,\n groupFromUserStorage: UserStorageSyncedWalletGroup | null,\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const shouldPushGroup = await syncGroupMetadataAndCheckIfPushNeeded(\n context,\n localGroup,\n groupFromUserStorage,\n profileId,\n );\n\n if (shouldPushGroup) {\n await pushGroupToUserStorage(context, localGroup, entropySourceId);\n }\n}\n\n/**\n * Syncs group metadata between local and user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param wallet - The local wallet containing the groups.\n * @param groupsFromUserStorage - Array of groups from user storage.\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function syncGroupsMetadata(\n context: BackupAndSyncContext,\n wallet: AccountWalletEntropyObject,\n groupsFromUserStorage: UserStorageSyncedWalletGroup[],\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const localSyncableGroupsToBePushedToUserStorage: AccountGroupMultichainAccountObject[] =\n [];\n\n const localSyncableGroups = getLocalGroupsForEntropyWallet(\n context,\n wallet.id,\n );\n\n for (const localSyncableGroup of localSyncableGroups) {\n const groupFromUserStorage = groupsFromUserStorage.find(\n (group) =>\n group.groupIndex === localSyncableGroup.metadata.entropy.groupIndex,\n );\n\n const shouldPushGroup = await syncGroupMetadataAndCheckIfPushNeeded(\n context,\n localSyncableGroup,\n groupFromUserStorage,\n profileId,\n );\n\n // Add to push list if any metadata needs to be updated in user storage\n if (shouldPushGroup) {\n localSyncableGroupsToBePushedToUserStorage.push(localSyncableGroup);\n }\n }\n\n // Push all groups that need to be updated to user storage\n if (localSyncableGroupsToBePushedToUserStorage.length > 0) {\n await pushGroupToUserStorageBatch(\n context,\n localSyncableGroupsToBePushedToUserStorage,\n entropySourceId,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"group.cjs","sourceRoot":"","sources":["../../../src/backup-and-sync/syncing/group.ts"],"names":[],"mappings":"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","sourcesContent":["import { toMultichainAccountWalletId } from '@metamask/account-api';\n\nimport type { AccountGroupMultichainAccountObject } from '../../group';\nimport { backupAndSyncLogger } from '../../logger';\nimport type { AccountWalletEntropyObject } from '../../wallet';\nimport type { BackupAndSyncAnalyticsAction } from '../analytics';\nimport { BackupAndSyncAnalyticsEvent } from '../analytics';\nimport type { ProfileId } from '../authentication';\nimport { UserStorageSyncedWalletGroupSchema } from '../types';\nimport type {\n BackupAndSyncContext,\n UserStorageSyncedWalletGroup,\n} from '../types';\nimport {\n pushGroupToUserStorage,\n pushGroupToUserStorageBatch,\n} from '../user-storage/network-operations';\nimport { getLocalGroupsForEntropyWallet } from '../utils';\nimport { toErrorMessage } from '../utils/errors';\nimport { compareAndSyncMetadata } from './metadata';\n\n/**\n * Creates multiple multichain account groups in batch (from 0 to maxGroupIndex).\n * This is an optimized version that creates all groups in one operation instead of\n * creating them sequentially.\n *\n * @param context - The sync context containing controller and messenger.\n * @param entropySourceId - The entropy source ID.\n * @param maxGroupIndex - Number of account groups to create in batch.\n * @param profileId - The profile ID for analytics.\n * @param analyticsAction - The analytics action to log for each created group.\n * @returns Array of created group IDs.\n */\nexport const createMultichainAccountGroupsBatch = async (\n context: BackupAndSyncContext,\n entropySourceId: string,\n maxGroupIndex: number,\n profileId: ProfileId,\n analyticsAction: BackupAndSyncAnalyticsAction,\n): Promise<void> => {\n const numberOfAccountGroupsToCreate = maxGroupIndex + 1; // maxGroupIndex is zero-based, so we add 1 to get the count.\n backupAndSyncLogger(\n `Creating ${numberOfAccountGroupsToCreate} account groups (batch) for entropy source: ${entropySourceId}`,\n );\n\n // Capture the set of group indices that already exist before the batch call,\n // so we can correctly identify newly created groups after the call completes.\n const walletId = toMultichainAccountWalletId(entropySourceId);\n const existingGroupIndices = new Set(\n getLocalGroupsForEntropyWallet(context, walletId).map(\n (group) => group.metadata.entropy.groupIndex,\n ),\n );\n\n try {\n // Call the batched creation method (this is idempotent).\n const groups = await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountGroups',\n {\n entropySource: entropySourceId,\n fromGroupIndex: 0,\n toGroupIndex: maxGroupIndex,\n },\n );\n\n // Contains all groups (existing + newly created).\n for (const group of groups) {\n // TODO: A group should not be null here, but EVM provider might fail to create some groups sometimes, which means\n // we can end up having an \"empty group\" for some time.\n if (group) {\n const didGroupAlreadyExist = existingGroupIndices.has(group.groupIndex);\n\n if (!didGroupAlreadyExist) {\n context.emitAnalyticsEventFn({\n action: analyticsAction,\n profileId,\n });\n }\n }\n }\n\n backupAndSyncLogger(`Successfully created ${groups.length} groups (batch)`);\n } catch (error) {\n // This can happen if the Snap Keyring is not ready yet when invoking\n // `MultichainAccountService:createMultichainAccountGroups`.\n // Since `MultichainAccountService:createMultichainAccountGroups` will at\n // least create the EVM account and the account group before throwing, we can safely\n // ignore this error and swallow it.\n // Any missing Snap accounts will be added later with alignment.\n\n backupAndSyncLogger(\n `Failed to create account groups batch:`,\n // istanbul ignore next\n toErrorMessage(error),\n );\n }\n};\n\n/**\n * Creates local groups from user storage groups.\n *\n * @param context - The sync context containing controller and messenger.\n * @param groupsFromUserStorage - Array of groups from user storage.\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function createLocalGroupsFromUserStorage(\n context: BackupAndSyncContext,\n groupsFromUserStorage: UserStorageSyncedWalletGroup[],\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const maxGroupIndex = Math.max(\n ...groupsFromUserStorage.map((group) => group.groupIndex),\n );\n\n // Creating multichain account group is idempotent, so we can safely\n // re-create every groups starting from 0.\n // Use batch creation for better performance.\n await createMultichainAccountGroupsBatch(\n context,\n entropySourceId,\n maxGroupIndex,\n profileId,\n BackupAndSyncAnalyticsEvent.GroupAdded,\n );\n}\n\n/**\n * Syncs group metadata fields and determines if the group needs to be pushed to user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param localGroup - The local group to sync.\n * @param groupFromUserStorage - The group from user storage to compare against.\n * @param profileId - The profile ID for analytics.\n * @returns A promise that resolves to true if the group needs to be pushed to user storage.\n */\nasync function syncGroupMetadataAndCheckIfPushNeeded(\n context: BackupAndSyncContext,\n localGroup: AccountGroupMultichainAccountObject,\n groupFromUserStorage: UserStorageSyncedWalletGroup | null | undefined,\n profileId: ProfileId,\n): Promise<boolean> {\n const groupPersistedMetadata =\n context.controller.state.accountGroupsMetadata[localGroup.id];\n\n if (!groupFromUserStorage) {\n backupAndSyncLogger(\n `Group ${localGroup.id} did not exist in user storage, pushing to user storage...`,\n );\n\n return true;\n }\n\n // Track if we need to push this group to user storage\n let shouldPushGroup = false;\n\n // Compare and sync name metadata\n const shouldPushForName = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.name,\n userStorageMetadata: groupFromUserStorage.name,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.name.schema.value.is(value),\n applyLocalUpdate: (name: string) => {\n context.controller.setAccountGroupName(localGroup.id, name, true);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupRenamed,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForName;\n\n // Compare and sync pinned metadata\n const shouldPushForPinned = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.pinned,\n userStorageMetadata: groupFromUserStorage.pinned,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.pinned.schema.value.is(value),\n applyLocalUpdate: (pinned: boolean) => {\n context.controller.setAccountGroupPinned(localGroup.id, pinned);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupPinnedStatusChanged,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForPinned;\n\n // Compare and sync hidden metadata\n const shouldPushForHidden = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.hidden,\n userStorageMetadata: groupFromUserStorage.hidden,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.hidden.schema.value.is(value),\n applyLocalUpdate: (hidden: boolean) => {\n context.controller.setAccountGroupHidden(localGroup.id, hidden);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupHiddenStatusChanged,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForHidden;\n\n return shouldPushGroup;\n}\n\n/**\n * Syncs a single group's metadata between local and user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param localGroup - The local group to sync.\n * @param groupFromUserStorage - The group from user storage to compare against (or null if it doesn't exist).\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function syncGroupMetadata(\n context: BackupAndSyncContext,\n localGroup: AccountGroupMultichainAccountObject,\n groupFromUserStorage: UserStorageSyncedWalletGroup | null,\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const shouldPushGroup = await syncGroupMetadataAndCheckIfPushNeeded(\n context,\n localGroup,\n groupFromUserStorage,\n profileId,\n );\n\n if (shouldPushGroup) {\n await pushGroupToUserStorage(context, localGroup, entropySourceId);\n }\n}\n\n/**\n * Syncs group metadata between local and user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param wallet - The local wallet containing the groups.\n * @param groupsFromUserStorage - Array of groups from user storage.\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function syncGroupsMetadata(\n context: BackupAndSyncContext,\n wallet: AccountWalletEntropyObject,\n groupsFromUserStorage: UserStorageSyncedWalletGroup[],\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const localSyncableGroupsToBePushedToUserStorage: AccountGroupMultichainAccountObject[] =\n [];\n\n const localSyncableGroups = getLocalGroupsForEntropyWallet(\n context,\n wallet.id,\n );\n\n for (const localSyncableGroup of localSyncableGroups) {\n const groupFromUserStorage = groupsFromUserStorage.find(\n (group) =>\n group.groupIndex === localSyncableGroup.metadata.entropy.groupIndex,\n );\n\n const shouldPushGroup = await syncGroupMetadataAndCheckIfPushNeeded(\n context,\n localSyncableGroup,\n groupFromUserStorage,\n profileId,\n );\n\n // Add to push list if any metadata needs to be updated in user storage\n if (shouldPushGroup) {\n localSyncableGroupsToBePushedToUserStorage.push(localSyncableGroup);\n }\n }\n\n // Push all groups that need to be updated to user storage\n if (localSyncableGroupsToBePushedToUserStorage.length > 0) {\n await pushGroupToUserStorageBatch(\n context,\n localSyncableGroupsToBePushedToUserStorage,\n entropySourceId,\n );\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"group.d.cts","sourceRoot":"","sources":["../../../src/backup-and-sync/syncing/group.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mCAAmC,EAAE,wBAAoB;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,yBAAqB;AAC/D,OAAO,KAAK,EAAE,4BAA4B,EAAE,+BAAqB;AAEjE,OAAO,KAAK,EAAE,SAAS,EAAE,oCAA0B;AAEnD,OAAO,KAAK,EACV,oBAAoB,EACpB,4BAA4B,EAC7B,qBAAiB;AASlB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kCAAkC,YACpC,oBAAoB,mBACZ,MAAM,iBACR,MAAM,aACV,SAAS,mBACH,4BAA4B,KAC5C,QAAQ,IAAI,CA6Dd,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,oBAAoB,EAC7B,qBAAqB,EAAE,4BAA4B,EAAE,EACrD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAef;AAwFD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,mCAAmC,EAC/C,oBAAoB,EAAE,4BAA4B,GAAG,IAAI,EACzD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,0BAA0B,EAClC,qBAAqB,EAAE,4BAA4B,EAAE,EACrD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAoCf"}
1
+ {"version":3,"file":"group.d.cts","sourceRoot":"","sources":["../../../src/backup-and-sync/syncing/group.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mCAAmC,EAAE,wBAAoB;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,yBAAqB;AAC/D,OAAO,KAAK,EAAE,4BAA4B,EAAE,+BAAqB;AAEjE,OAAO,KAAK,EAAE,SAAS,EAAE,oCAA0B;AAEnD,OAAO,KAAK,EACV,oBAAoB,EACpB,4BAA4B,EAC7B,qBAAiB;AASlB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kCAAkC,YACpC,oBAAoB,mBACZ,MAAM,iBACR,MAAM,aACV,SAAS,mBACH,4BAA4B,KAC5C,QAAQ,IAAI,CAyDd,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,oBAAoB,EAC7B,qBAAqB,EAAE,4BAA4B,EAAE,EACrD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAef;AAwFD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,mCAAmC,EAC/C,oBAAoB,EAAE,4BAA4B,GAAG,IAAI,EACzD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,0BAA0B,EAClC,qBAAqB,EAAE,4BAA4B,EAAE,EACrD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAoCf"}
@@ -1 +1 @@
1
- {"version":3,"file":"group.d.mts","sourceRoot":"","sources":["../../../src/backup-and-sync/syncing/group.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mCAAmC,EAAE,wBAAoB;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,yBAAqB;AAC/D,OAAO,KAAK,EAAE,4BAA4B,EAAE,+BAAqB;AAEjE,OAAO,KAAK,EAAE,SAAS,EAAE,oCAA0B;AAEnD,OAAO,KAAK,EACV,oBAAoB,EACpB,4BAA4B,EAC7B,qBAAiB;AASlB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kCAAkC,YACpC,oBAAoB,mBACZ,MAAM,iBACR,MAAM,aACV,SAAS,mBACH,4BAA4B,KAC5C,QAAQ,IAAI,CA6Dd,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,oBAAoB,EAC7B,qBAAqB,EAAE,4BAA4B,EAAE,EACrD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAef;AAwFD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,mCAAmC,EAC/C,oBAAoB,EAAE,4BAA4B,GAAG,IAAI,EACzD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,0BAA0B,EAClC,qBAAqB,EAAE,4BAA4B,EAAE,EACrD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAoCf"}
1
+ {"version":3,"file":"group.d.mts","sourceRoot":"","sources":["../../../src/backup-and-sync/syncing/group.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mCAAmC,EAAE,wBAAoB;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,yBAAqB;AAC/D,OAAO,KAAK,EAAE,4BAA4B,EAAE,+BAAqB;AAEjE,OAAO,KAAK,EAAE,SAAS,EAAE,oCAA0B;AAEnD,OAAO,KAAK,EACV,oBAAoB,EACpB,4BAA4B,EAC7B,qBAAiB;AASlB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kCAAkC,YACpC,oBAAoB,mBACZ,MAAM,iBACR,MAAM,aACV,SAAS,mBACH,4BAA4B,KAC5C,QAAQ,IAAI,CAyDd,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,oBAAoB,EAC7B,qBAAqB,EAAE,4BAA4B,EAAE,EACrD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAef;AAwFD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,mCAAmC,EAC/C,oBAAoB,EAAE,4BAA4B,GAAG,IAAI,EACzD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,0BAA0B,EAClC,qBAAqB,EAAE,4BAA4B,EAAE,EACrD,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAoCf"}
@@ -19,9 +19,6 @@ import { compareAndSyncMetadata } from "./metadata.mjs";
19
19
  * @returns Array of created group IDs.
20
20
  */
21
21
  export const createMultichainAccountGroupsBatch = async (context, entropySourceId, maxGroupIndex, profileId, analyticsAction) => {
22
- console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Creating ${maxGroupIndex + 1} account groups (batch) for entropy source: ${entropySourceId}`);
23
- console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Max group index: ${maxGroupIndex}`);
24
- console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Context: ${JSON.stringify(context)}`);
25
22
  const numberOfAccountGroupsToCreate = maxGroupIndex + 1; // maxGroupIndex is zero-based, so we add 1 to get the count.
26
23
  backupAndSyncLogger(`Creating ${numberOfAccountGroupsToCreate} account groups (batch) for entropy source: ${entropySourceId}`);
27
24
  // Capture the set of group indices that already exist before the batch call,
@@ -1 +1 @@
1
- {"version":3,"file":"group.mjs","sourceRoot":"","sources":["../../../src/backup-and-sync/syncing/group.ts"],"names":[],"mappings":"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","sourcesContent":["import { toMultichainAccountWalletId } from '@metamask/account-api';\n\nimport type { AccountGroupMultichainAccountObject } from '../../group';\nimport { backupAndSyncLogger } from '../../logger';\nimport type { AccountWalletEntropyObject } from '../../wallet';\nimport type { BackupAndSyncAnalyticsAction } from '../analytics';\nimport { BackupAndSyncAnalyticsEvent } from '../analytics';\nimport type { ProfileId } from '../authentication';\nimport { UserStorageSyncedWalletGroupSchema } from '../types';\nimport type {\n BackupAndSyncContext,\n UserStorageSyncedWalletGroup,\n} from '../types';\nimport {\n pushGroupToUserStorage,\n pushGroupToUserStorageBatch,\n} from '../user-storage/network-operations';\nimport { getLocalGroupsForEntropyWallet } from '../utils';\nimport { toErrorMessage } from '../utils/errors';\nimport { compareAndSyncMetadata } from './metadata';\n\n/**\n * Creates multiple multichain account groups in batch (from 0 to maxGroupIndex).\n * This is an optimized version that creates all groups in one operation instead of\n * creating them sequentially.\n *\n * @param context - The sync context containing controller and messenger.\n * @param entropySourceId - The entropy source ID.\n * @param maxGroupIndex - Number of account groups to create in batch.\n * @param profileId - The profile ID for analytics.\n * @param analyticsAction - The analytics action to log for each created group.\n * @returns Array of created group IDs.\n */\nexport const createMultichainAccountGroupsBatch = async (\n context: BackupAndSyncContext,\n entropySourceId: string,\n maxGroupIndex: number,\n profileId: ProfileId,\n analyticsAction: BackupAndSyncAnalyticsAction,\n): Promise<void> => {\n console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Creating ${maxGroupIndex + 1} account groups (batch) for entropy source: ${entropySourceId}`);\n console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Max group index: ${maxGroupIndex}`);\n console.log(`[PERFORMANCE DEBUG] createMultichainAccountGroupsBatch - Context: ${JSON.stringify(context)}`);\n\n const numberOfAccountGroupsToCreate = maxGroupIndex + 1; // maxGroupIndex is zero-based, so we add 1 to get the count.\n backupAndSyncLogger(\n `Creating ${numberOfAccountGroupsToCreate} account groups (batch) for entropy source: ${entropySourceId}`,\n );\n\n // Capture the set of group indices that already exist before the batch call,\n // so we can correctly identify newly created groups after the call completes.\n const walletId = toMultichainAccountWalletId(entropySourceId);\n const existingGroupIndices = new Set(\n getLocalGroupsForEntropyWallet(context, walletId).map(\n (group) => group.metadata.entropy.groupIndex,\n ),\n );\n\n try {\n // Call the batched creation method (this is idempotent).\n const groups = await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountGroups',\n {\n entropySource: entropySourceId,\n fromGroupIndex: 0,\n toGroupIndex: maxGroupIndex,\n },\n );\n\n // Contains all groups (existing + newly created).\n for (const group of groups) {\n // TODO: A group should not be null here, but EVM provider might fail to create some groups sometimes, which means\n // we can end up having an \"empty group\" for some time.\n if (group) {\n const didGroupAlreadyExist = existingGroupIndices.has(group.groupIndex);\n\n if (!didGroupAlreadyExist) {\n context.emitAnalyticsEventFn({\n action: analyticsAction,\n profileId,\n });\n }\n }\n }\n\n backupAndSyncLogger(`Successfully created ${groups.length} groups (batch)`);\n } catch (error) {\n // This can happen if the Snap Keyring is not ready yet when invoking\n // `MultichainAccountService:createMultichainAccountGroups`.\n // Since `MultichainAccountService:createMultichainAccountGroups` will at\n // least create the EVM account and the account group before throwing, we can safely\n // ignore this error and swallow it.\n // Any missing Snap accounts will be added later with alignment.\n\n backupAndSyncLogger(\n `Failed to create account groups batch:`,\n // istanbul ignore next\n toErrorMessage(error),\n );\n }\n};\n\n/**\n * Creates local groups from user storage groups.\n *\n * @param context - The sync context containing controller and messenger.\n * @param groupsFromUserStorage - Array of groups from user storage.\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function createLocalGroupsFromUserStorage(\n context: BackupAndSyncContext,\n groupsFromUserStorage: UserStorageSyncedWalletGroup[],\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const maxGroupIndex = Math.max(\n ...groupsFromUserStorage.map((group) => group.groupIndex),\n );\n\n // Creating multichain account group is idempotent, so we can safely\n // re-create every groups starting from 0.\n // Use batch creation for better performance.\n await createMultichainAccountGroupsBatch(\n context,\n entropySourceId,\n maxGroupIndex,\n profileId,\n BackupAndSyncAnalyticsEvent.GroupAdded,\n );\n}\n\n/**\n * Syncs group metadata fields and determines if the group needs to be pushed to user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param localGroup - The local group to sync.\n * @param groupFromUserStorage - The group from user storage to compare against.\n * @param profileId - The profile ID for analytics.\n * @returns A promise that resolves to true if the group needs to be pushed to user storage.\n */\nasync function syncGroupMetadataAndCheckIfPushNeeded(\n context: BackupAndSyncContext,\n localGroup: AccountGroupMultichainAccountObject,\n groupFromUserStorage: UserStorageSyncedWalletGroup | null | undefined,\n profileId: ProfileId,\n): Promise<boolean> {\n const groupPersistedMetadata =\n context.controller.state.accountGroupsMetadata[localGroup.id];\n\n if (!groupFromUserStorage) {\n backupAndSyncLogger(\n `Group ${localGroup.id} did not exist in user storage, pushing to user storage...`,\n );\n\n return true;\n }\n\n // Track if we need to push this group to user storage\n let shouldPushGroup = false;\n\n // Compare and sync name metadata\n const shouldPushForName = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.name,\n userStorageMetadata: groupFromUserStorage.name,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.name.schema.value.is(value),\n applyLocalUpdate: (name: string) => {\n context.controller.setAccountGroupName(localGroup.id, name, true);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupRenamed,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForName;\n\n // Compare and sync pinned metadata\n const shouldPushForPinned = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.pinned,\n userStorageMetadata: groupFromUserStorage.pinned,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.pinned.schema.value.is(value),\n applyLocalUpdate: (pinned: boolean) => {\n context.controller.setAccountGroupPinned(localGroup.id, pinned);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupPinnedStatusChanged,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForPinned;\n\n // Compare and sync hidden metadata\n const shouldPushForHidden = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.hidden,\n userStorageMetadata: groupFromUserStorage.hidden,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.hidden.schema.value.is(value),\n applyLocalUpdate: (hidden: boolean) => {\n context.controller.setAccountGroupHidden(localGroup.id, hidden);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupHiddenStatusChanged,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForHidden;\n\n return shouldPushGroup;\n}\n\n/**\n * Syncs a single group's metadata between local and user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param localGroup - The local group to sync.\n * @param groupFromUserStorage - The group from user storage to compare against (or null if it doesn't exist).\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function syncGroupMetadata(\n context: BackupAndSyncContext,\n localGroup: AccountGroupMultichainAccountObject,\n groupFromUserStorage: UserStorageSyncedWalletGroup | null,\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const shouldPushGroup = await syncGroupMetadataAndCheckIfPushNeeded(\n context,\n localGroup,\n groupFromUserStorage,\n profileId,\n );\n\n if (shouldPushGroup) {\n await pushGroupToUserStorage(context, localGroup, entropySourceId);\n }\n}\n\n/**\n * Syncs group metadata between local and user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param wallet - The local wallet containing the groups.\n * @param groupsFromUserStorage - Array of groups from user storage.\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function syncGroupsMetadata(\n context: BackupAndSyncContext,\n wallet: AccountWalletEntropyObject,\n groupsFromUserStorage: UserStorageSyncedWalletGroup[],\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const localSyncableGroupsToBePushedToUserStorage: AccountGroupMultichainAccountObject[] =\n [];\n\n const localSyncableGroups = getLocalGroupsForEntropyWallet(\n context,\n wallet.id,\n );\n\n for (const localSyncableGroup of localSyncableGroups) {\n const groupFromUserStorage = groupsFromUserStorage.find(\n (group) =>\n group.groupIndex === localSyncableGroup.metadata.entropy.groupIndex,\n );\n\n const shouldPushGroup = await syncGroupMetadataAndCheckIfPushNeeded(\n context,\n localSyncableGroup,\n groupFromUserStorage,\n profileId,\n );\n\n // Add to push list if any metadata needs to be updated in user storage\n if (shouldPushGroup) {\n localSyncableGroupsToBePushedToUserStorage.push(localSyncableGroup);\n }\n }\n\n // Push all groups that need to be updated to user storage\n if (localSyncableGroupsToBePushedToUserStorage.length > 0) {\n await pushGroupToUserStorageBatch(\n context,\n localSyncableGroupsToBePushedToUserStorage,\n entropySourceId,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"group.mjs","sourceRoot":"","sources":["../../../src/backup-and-sync/syncing/group.ts"],"names":[],"mappings":"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","sourcesContent":["import { toMultichainAccountWalletId } from '@metamask/account-api';\n\nimport type { AccountGroupMultichainAccountObject } from '../../group';\nimport { backupAndSyncLogger } from '../../logger';\nimport type { AccountWalletEntropyObject } from '../../wallet';\nimport type { BackupAndSyncAnalyticsAction } from '../analytics';\nimport { BackupAndSyncAnalyticsEvent } from '../analytics';\nimport type { ProfileId } from '../authentication';\nimport { UserStorageSyncedWalletGroupSchema } from '../types';\nimport type {\n BackupAndSyncContext,\n UserStorageSyncedWalletGroup,\n} from '../types';\nimport {\n pushGroupToUserStorage,\n pushGroupToUserStorageBatch,\n} from '../user-storage/network-operations';\nimport { getLocalGroupsForEntropyWallet } from '../utils';\nimport { toErrorMessage } from '../utils/errors';\nimport { compareAndSyncMetadata } from './metadata';\n\n/**\n * Creates multiple multichain account groups in batch (from 0 to maxGroupIndex).\n * This is an optimized version that creates all groups in one operation instead of\n * creating them sequentially.\n *\n * @param context - The sync context containing controller and messenger.\n * @param entropySourceId - The entropy source ID.\n * @param maxGroupIndex - Number of account groups to create in batch.\n * @param profileId - The profile ID for analytics.\n * @param analyticsAction - The analytics action to log for each created group.\n * @returns Array of created group IDs.\n */\nexport const createMultichainAccountGroupsBatch = async (\n context: BackupAndSyncContext,\n entropySourceId: string,\n maxGroupIndex: number,\n profileId: ProfileId,\n analyticsAction: BackupAndSyncAnalyticsAction,\n): Promise<void> => {\n const numberOfAccountGroupsToCreate = maxGroupIndex + 1; // maxGroupIndex is zero-based, so we add 1 to get the count.\n backupAndSyncLogger(\n `Creating ${numberOfAccountGroupsToCreate} account groups (batch) for entropy source: ${entropySourceId}`,\n );\n\n // Capture the set of group indices that already exist before the batch call,\n // so we can correctly identify newly created groups after the call completes.\n const walletId = toMultichainAccountWalletId(entropySourceId);\n const existingGroupIndices = new Set(\n getLocalGroupsForEntropyWallet(context, walletId).map(\n (group) => group.metadata.entropy.groupIndex,\n ),\n );\n\n try {\n // Call the batched creation method (this is idempotent).\n const groups = await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountGroups',\n {\n entropySource: entropySourceId,\n fromGroupIndex: 0,\n toGroupIndex: maxGroupIndex,\n },\n );\n\n // Contains all groups (existing + newly created).\n for (const group of groups) {\n // TODO: A group should not be null here, but EVM provider might fail to create some groups sometimes, which means\n // we can end up having an \"empty group\" for some time.\n if (group) {\n const didGroupAlreadyExist = existingGroupIndices.has(group.groupIndex);\n\n if (!didGroupAlreadyExist) {\n context.emitAnalyticsEventFn({\n action: analyticsAction,\n profileId,\n });\n }\n }\n }\n\n backupAndSyncLogger(`Successfully created ${groups.length} groups (batch)`);\n } catch (error) {\n // This can happen if the Snap Keyring is not ready yet when invoking\n // `MultichainAccountService:createMultichainAccountGroups`.\n // Since `MultichainAccountService:createMultichainAccountGroups` will at\n // least create the EVM account and the account group before throwing, we can safely\n // ignore this error and swallow it.\n // Any missing Snap accounts will be added later with alignment.\n\n backupAndSyncLogger(\n `Failed to create account groups batch:`,\n // istanbul ignore next\n toErrorMessage(error),\n );\n }\n};\n\n/**\n * Creates local groups from user storage groups.\n *\n * @param context - The sync context containing controller and messenger.\n * @param groupsFromUserStorage - Array of groups from user storage.\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function createLocalGroupsFromUserStorage(\n context: BackupAndSyncContext,\n groupsFromUserStorage: UserStorageSyncedWalletGroup[],\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const maxGroupIndex = Math.max(\n ...groupsFromUserStorage.map((group) => group.groupIndex),\n );\n\n // Creating multichain account group is idempotent, so we can safely\n // re-create every groups starting from 0.\n // Use batch creation for better performance.\n await createMultichainAccountGroupsBatch(\n context,\n entropySourceId,\n maxGroupIndex,\n profileId,\n BackupAndSyncAnalyticsEvent.GroupAdded,\n );\n}\n\n/**\n * Syncs group metadata fields and determines if the group needs to be pushed to user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param localGroup - The local group to sync.\n * @param groupFromUserStorage - The group from user storage to compare against.\n * @param profileId - The profile ID for analytics.\n * @returns A promise that resolves to true if the group needs to be pushed to user storage.\n */\nasync function syncGroupMetadataAndCheckIfPushNeeded(\n context: BackupAndSyncContext,\n localGroup: AccountGroupMultichainAccountObject,\n groupFromUserStorage: UserStorageSyncedWalletGroup | null | undefined,\n profileId: ProfileId,\n): Promise<boolean> {\n const groupPersistedMetadata =\n context.controller.state.accountGroupsMetadata[localGroup.id];\n\n if (!groupFromUserStorage) {\n backupAndSyncLogger(\n `Group ${localGroup.id} did not exist in user storage, pushing to user storage...`,\n );\n\n return true;\n }\n\n // Track if we need to push this group to user storage\n let shouldPushGroup = false;\n\n // Compare and sync name metadata\n const shouldPushForName = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.name,\n userStorageMetadata: groupFromUserStorage.name,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.name.schema.value.is(value),\n applyLocalUpdate: (name: string) => {\n context.controller.setAccountGroupName(localGroup.id, name, true);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupRenamed,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForName;\n\n // Compare and sync pinned metadata\n const shouldPushForPinned = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.pinned,\n userStorageMetadata: groupFromUserStorage.pinned,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.pinned.schema.value.is(value),\n applyLocalUpdate: (pinned: boolean) => {\n context.controller.setAccountGroupPinned(localGroup.id, pinned);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupPinnedStatusChanged,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForPinned;\n\n // Compare and sync hidden metadata\n const shouldPushForHidden = await compareAndSyncMetadata({\n context,\n localMetadata: groupPersistedMetadata?.hidden,\n userStorageMetadata: groupFromUserStorage.hidden,\n validateUserStorageValue: (value) =>\n UserStorageSyncedWalletGroupSchema.schema.hidden.schema.value.is(value),\n applyLocalUpdate: (hidden: boolean) => {\n context.controller.setAccountGroupHidden(localGroup.id, hidden);\n },\n analytics: {\n action: BackupAndSyncAnalyticsEvent.GroupHiddenStatusChanged,\n profileId,\n },\n });\n\n shouldPushGroup ||= shouldPushForHidden;\n\n return shouldPushGroup;\n}\n\n/**\n * Syncs a single group's metadata between local and user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param localGroup - The local group to sync.\n * @param groupFromUserStorage - The group from user storage to compare against (or null if it doesn't exist).\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function syncGroupMetadata(\n context: BackupAndSyncContext,\n localGroup: AccountGroupMultichainAccountObject,\n groupFromUserStorage: UserStorageSyncedWalletGroup | null,\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const shouldPushGroup = await syncGroupMetadataAndCheckIfPushNeeded(\n context,\n localGroup,\n groupFromUserStorage,\n profileId,\n );\n\n if (shouldPushGroup) {\n await pushGroupToUserStorage(context, localGroup, entropySourceId);\n }\n}\n\n/**\n * Syncs group metadata between local and user storage.\n *\n * @param context - The sync context containing controller and messenger.\n * @param wallet - The local wallet containing the groups.\n * @param groupsFromUserStorage - Array of groups from user storage.\n * @param entropySourceId - The entropy source ID.\n * @param profileId - The profile ID for analytics.\n */\nexport async function syncGroupsMetadata(\n context: BackupAndSyncContext,\n wallet: AccountWalletEntropyObject,\n groupsFromUserStorage: UserStorageSyncedWalletGroup[],\n entropySourceId: string,\n profileId: ProfileId,\n): Promise<void> {\n const localSyncableGroupsToBePushedToUserStorage: AccountGroupMultichainAccountObject[] =\n [];\n\n const localSyncableGroups = getLocalGroupsForEntropyWallet(\n context,\n wallet.id,\n );\n\n for (const localSyncableGroup of localSyncableGroups) {\n const groupFromUserStorage = groupsFromUserStorage.find(\n (group) =>\n group.groupIndex === localSyncableGroup.metadata.entropy.groupIndex,\n );\n\n const shouldPushGroup = await syncGroupMetadataAndCheckIfPushNeeded(\n context,\n localSyncableGroup,\n groupFromUserStorage,\n profileId,\n );\n\n // Add to push list if any metadata needs to be updated in user storage\n if (shouldPushGroup) {\n localSyncableGroupsToBePushedToUserStorage.push(localSyncableGroup);\n }\n }\n\n // Push all groups that need to be updated to user storage\n if (localSyncableGroupsToBePushedToUserStorage.length > 0) {\n await pushGroupToUserStorageBatch(\n context,\n localSyncableGroupsToBePushedToUserStorage,\n entropySourceId,\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/account-tree-controller",
3
- "version": "7.1.0-preview-a89313ea9",
3
+ "version": "7.1.0-preview-dccbcec3e",
4
4
  "description": "Controller to group account together based on some pre-defined rules",
5
5
  "keywords": [
6
6
  "Ethereum",