@metamask-previews/account-tree-controller 8.1.0-preview-d8fceeabc → 8.1.0-preview-efd9e28b2
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.
- package/CHANGELOG.md +0 -10
- package/dist/state/import.cjs +4 -8
- package/dist/state/import.cjs.map +1 -1
- package/dist/state/import.d.cts.map +1 -1
- package/dist/state/import.d.mts.map +1 -1
- package/dist/state/import.mjs +4 -8
- package/dist/state/import.mjs.map +1 -1
- package/dist/state/payload.cjs +4 -4
- package/dist/state/payload.cjs.map +1 -1
- package/dist/state/payload.d.cts +37 -37
- package/dist/state/payload.d.cts.map +1 -1
- package/dist/state/payload.d.mts +37 -37
- package/dist/state/payload.d.mts.map +1 -1
- package/dist/state/payload.mjs +4 -4
- package/dist/state/payload.mjs.map +1 -1
- package/dist/state/snapshot.cjs +2 -49
- package/dist/state/snapshot.cjs.map +1 -1
- package/dist/state/snapshot.d.cts +2 -25
- package/dist/state/snapshot.d.cts.map +1 -1
- package/dist/state/snapshot.d.mts +2 -25
- package/dist/state/snapshot.d.mts.map +1 -1
- package/dist/state/snapshot.mjs +2 -49
- package/dist/state/snapshot.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,16 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
### Added
|
|
11
|
-
|
|
12
|
-
- Add `AccountTreeSnapshot:strip{Metadata,Secrets}` support ([#10112](https://github.com/MetaMask/core/pull/10112))
|
|
13
|
-
- This can be used to mutate the snapshot before calling `:importState` and ease custom flow integration where secrets and metadata would be imported in 2-steps.
|
|
14
|
-
|
|
15
|
-
### Changed
|
|
16
|
-
|
|
17
|
-
- **BREAKING:** `metadata` is now optional on `AccountWalletPayloadMetadata`, `AccountWalletGroupPayloadMetadata`, and all wallet/group payload entry types ([#10112](https://github.com/MetaMask/core/pull/10112))
|
|
18
|
-
- Consumers reading `metadata` from a snapshot or payload must now guard against `undefined` (e.g. after calling `AccountTreeSnapshot.stripMetadata()`).
|
|
19
|
-
|
|
20
10
|
## [8.1.0]
|
|
21
11
|
|
|
22
12
|
### Added
|
package/dist/state/import.cjs
CHANGED
|
@@ -92,11 +92,9 @@ function hasLocalGroupPrivateKey(localWallet, group) {
|
|
|
92
92
|
* @param payloadGroupMetadata - Metadata from the payload group entry.
|
|
93
93
|
*/
|
|
94
94
|
function setGroupMetadata(context, localGroupId, payloadGroupMetadata) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
context.setAccountGroupHidden(localGroupId, payloadGroupMetadata.hidden);
|
|
99
|
-
}
|
|
95
|
+
context.setAccountGroupName(localGroupId, payloadGroupMetadata.name);
|
|
96
|
+
context.setAccountGroupPinned(localGroupId, payloadGroupMetadata.pinned);
|
|
97
|
+
context.setAccountGroupHidden(localGroupId, payloadGroupMetadata.hidden);
|
|
100
98
|
}
|
|
101
99
|
/**
|
|
102
100
|
* Computes the contiguous ranges of group indices that are present in the payload
|
|
@@ -154,9 +152,7 @@ async function importMnemonicWallet(context, payloadWallet) {
|
|
|
154
152
|
// Event handlers fire synchronously, so the wallet is in the tree now.
|
|
155
153
|
localWallet = findLocalWalletMnemonicFromId(context, id);
|
|
156
154
|
}
|
|
157
|
-
|
|
158
|
-
context.setWalletName(localWallet.id, payloadWallet.metadata.name);
|
|
159
|
-
}
|
|
155
|
+
context.setWalletName(localWallet.id, payloadWallet.metadata.name);
|
|
160
156
|
// Apply metadata to groups that are already present locally before attempting
|
|
161
157
|
// to create missing ones. If createMultichainAccountGroups throws partway
|
|
162
158
|
// through, these groups would otherwise be left without their payload metadata.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.cjs","sourceRoot":"","sources":["../../src/state/import.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AccountWalletType,\n toAccountGroupId,\n toAccountWalletId,\n toMultichainAccountGroupId,\n} from '@metamask/account-api';\nimport type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport { HdKeyring } from '@metamask/eth-hd-keyring/v2';\nimport { EthAccountType } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\n\nimport type {\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n} from '../types.js';\nimport type {\n AccountWalletEntropyObject,\n AccountWalletKeyringObject,\n} from '../wallet.js';\nimport { isMnemonicWalletObject } from './export.js';\nimport type {\n AccountWalletMnemonicGroupEntry,\n AccountWalletMnemonicPayload,\n AccountWalletPayloadId,\n AccountWalletPrivateKeyGroupEntry,\n} from './payload.js';\nimport {\n AccountWalletPayloadType,\n parsePayloadGroupId,\n toWalletPayloadId,\n} from './payload.js';\nimport type { AccountTreeSnapshot } from './snapshot.js';\nimport { decodeBytes } from './utils.js';\n\n/** Context required by {@link importState}. */\nexport type ImportContext = {\n getState: () => AccountTreeControllerState;\n messenger: AccountTreeControllerMessenger;\n setWalletName: (walletId: AccountWalletId, name: string) => void;\n /** Sets a group name. Implementations must resolve name conflicts automatically. */\n setAccountGroupName: (groupId: AccountGroupId, name: string) => void;\n setAccountGroupPinned: (groupId: AccountGroupId, pinned: boolean) => void;\n setAccountGroupHidden: (groupId: AccountGroupId, hidden: boolean) => void;\n};\n\n/**\n * Searches the local wallet tree for an entropy wallet whose stable payload ID\n * matches `payloadWalletId`. The entropy source ID is derived on-the-fly via\n * `KeyringController:withKeyringV2Unsafe` rather than relying on cached metadata.\n *\n * @param context - Import context.\n * @param payloadWalletId - Payload wallet ID to match against.\n * @returns The matching local entropy wallet, or `undefined` if not found.\n */\nasync function findLocalWalletMnemonicFromPayloadId(\n context: ImportContext,\n payloadWalletId: AccountWalletPayloadId,\n): Promise<AccountWalletEntropyObject | undefined> {\n const wallets = Object.values(context.getState().accountTree.wallets);\n\n for (const wallet of wallets) {\n if (isMnemonicWalletObject(wallet)) {\n const result = await context.messenger.call(\n 'KeyringController:withKeyringV2Unsafe',\n { id: wallet.metadata.entropy.id },\n async ({ keyring }) => {\n const hdKeyring = keyring as HdKeyring;\n\n return toWalletPayloadId(await hdKeyring.toEntropySourceId());\n },\n );\n\n const localPayloadId = result as AccountWalletPayloadId;\n if (localPayloadId === payloadWalletId) {\n return wallet;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Returns the local entropy wallet for the given ID.\n *\n * @param context - Import context.\n * @param id - Local wallet ID.\n * @returns The entropy wallet object.\n * @throws If the wallet is not found or is not an entropy wallet.\n */\nfunction findLocalWalletMnemonicFromId(\n context: ImportContext,\n id: AccountWalletId,\n): AccountWalletEntropyObject {\n const localWallets = context.getState().accountTree.wallets;\n const localWallet = localWallets[id];\n\n if (!localWallet) {\n throw new Error(\n `Failed to import mnemonic wallet: wallet not found after creation`,\n );\n }\n if (!isMnemonicWalletObject(localWallet)) {\n throw new Error(\n `Failed to import mnemonic wallet: wallet is not of type 'mnemonic'`,\n );\n }\n return localWallet;\n}\n\n/**\n * Returns the local simple-keyring wallet, or `undefined` if none exists yet.\n *\n * The private-key wallet ID is static (derived solely from {@link KeyringTypes.simple}),\n * so no runtime argument is needed to locate it.\n *\n * @param context - Import context.\n * @returns The keyring wallet object, or `undefined` if not present in state.\n */\nfunction findLocalWalletPrivateKey(\n context: ImportContext,\n): AccountWalletKeyringObject | undefined {\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n const localWallet = context.getState().accountTree.wallets[localWalletId];\n return localWallet?.type === AccountWalletType.Keyring\n ? localWallet\n : undefined;\n}\n\n/**\n * Returns `true` if the given payload group is already present in the local simple-keyring wallet.\n *\n * @param localWallet - The local simple-keyring wallet, or `undefined` if none exists yet.\n * @param group - The payload group entry to check.\n * @returns Whether the group's account is already tracked locally.\n */\nfunction hasLocalGroupPrivateKey(\n localWallet: AccountWalletKeyringObject | undefined,\n group: AccountWalletPrivateKeyGroupEntry,\n): boolean {\n const address = parsePayloadGroupId(group.id).subId;\n\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n const localGroupId = toAccountGroupId(localWalletId, address);\n const localGroup = localWallet?.groups[localGroupId];\n\n const accountId = getUUIDFromAddressOfNormalAccount(address);\n\n return localGroup?.accounts.some((id) => id === accountId) ?? false;\n}\n\n/**\n * Applies name, pinned, and hidden metadata from a payload group entry to a local group.\n *\n * @param context - Import context providing the metadata setters.\n * @param localGroupId - Local group ID to update.\n * @param payloadGroupMetadata - Metadata from the payload group entry.\n */\nfunction setGroupMetadata(\n context: ImportContext,\n localGroupId: AccountGroupId,\n payloadGroupMetadata: AccountWalletMnemonicGroupEntry['metadata'],\n): void {\n if (payloadGroupMetadata) {\n context.setAccountGroupName(localGroupId, payloadGroupMetadata.name);\n context.setAccountGroupPinned(localGroupId, payloadGroupMetadata.pinned);\n context.setAccountGroupHidden(localGroupId, payloadGroupMetadata.hidden);\n }\n}\n\n/**\n * Computes the contiguous ranges of group indices that are present in the payload\n * but absent from the local wallet, so they can be created in batches.\n *\n * @param localWallet - The local entropy wallet to check existing groups against.\n * @param payloadGroups - Ordered group entries from the payload.\n * @returns An array of `[fromGroupIndex, toGroupIndex]` ranges to create.\n */\nfunction getRangesFromPayloadGroups(\n localWallet: AccountWalletEntropyObject,\n payloadGroups: AccountWalletMnemonicGroupEntry[],\n): [number, number][] {\n let rangeIndex: number | undefined;\n const ranges: [number, number][] = [];\n\n // Keep track of the last payload group so we can close the final range if needed.\n let lastPayloadGroup: AccountWalletMnemonicGroupEntry | undefined;\n for (const payloadGroup of payloadGroups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n\n if (localWallet.groups[localGroupId]) {\n if (rangeIndex !== undefined) {\n ranges.push([rangeIndex, payloadGroup.groupIndex - 1]);\n rangeIndex = undefined;\n }\n continue;\n }\n\n rangeIndex ??= payloadGroup.groupIndex;\n lastPayloadGroup = payloadGroup;\n }\n\n if (rangeIndex !== undefined && lastPayloadGroup !== undefined) {\n ranges.push([rangeIndex, lastPayloadGroup.groupIndex]);\n }\n\n return ranges;\n}\n\n/**\n * Applies a mnemonic wallet payload entry to the local state.\n *\n * If no local wallet with the same entropy source ID exists and a mnemonic is\n * present in the payload, a new HD wallet is created via\n * `MultichainAccountService:createMultichainAccountWallet`. Missing groups are\n * created in batches via `MultichainAccountService:createMultichainAccountGroups`.\n * Metadata (name, pinned, hidden) is applied to all groups afterward.\n *\n * @param context - Import context.\n * @param payloadWallet - The mnemonic wallet entry from the payload.\n */\nasync function importMnemonicWallet(\n context: ImportContext,\n payloadWallet: AccountWalletMnemonicPayload,\n): Promise<void> {\n // Find the local wallet with the same entropy source ID if it exists.\n let localWallet = await findLocalWalletMnemonicFromPayloadId(\n context,\n payloadWallet.id,\n );\n\n if (!localWallet) {\n if (!payloadWallet.value) {\n // No mnemonic in payload and wallet doesn't exist locally -- nothing to do.\n return;\n }\n\n // Import the mnemonic as a new HD wallet.\n const mnemonic = decodeBytes(payloadWallet.value);\n const { id } = await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountWallet',\n { type: 'import', mnemonic },\n );\n\n // Event handlers fire synchronously, so the wallet is in the tree now.\n localWallet = findLocalWalletMnemonicFromId(context, id);\n }\n\n if (payloadWallet.metadata) {\n context.setWalletName(localWallet.id, payloadWallet.metadata.name);\n }\n\n // Apply metadata to groups that are already present locally before attempting\n // to create missing ones. If createMultichainAccountGroups throws partway\n // through, these groups would otherwise be left without their payload metadata.\n const localExistingGroupIds = new Set(Object.keys(localWallet.groups));\n for (const payloadGroup of payloadWallet.groups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n if (localExistingGroupIds.has(localGroupId)) {\n setGroupMetadata(context, localGroupId, payloadGroup.metadata);\n }\n }\n\n for (const range of getRangesFromPayloadGroups(\n localWallet,\n payloadWallet.groups,\n )) {\n await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountGroups',\n {\n entropySource: localWallet.metadata.entropy.id,\n fromGroupIndex: range[0],\n toGroupIndex: range[1],\n },\n );\n }\n\n // Re-read wallet after groups creation.\n localWallet = findLocalWalletMnemonicFromId(context, localWallet.id);\n\n // Apply metadata to newly created groups. Skip groups that were already\n // handled above, and guard against groups that failed to be created so a\n // partial failure doesn't throw and abort the rest of the snapshot import.\n for (const payloadGroup of payloadWallet.groups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n if (\n localExistingGroupIds.has(localGroupId) ||\n !localWallet.groups[localGroupId]\n ) {\n continue;\n }\n setGroupMetadata(context, localGroupId, payloadGroup.metadata);\n }\n}\n\n/**\n * Applies private-key wallet group entries from the payload to the local state.\n *\n * For each group the account address is derived from the payload group ID. If the\n * account does not yet exist locally and a private key is provided, it is imported\n * via `KeyringController:withKeyringV2` using the `'private-key:import'` constructor.\n * Metadata (name, pinned, hidden) is then applied to the local group.\n *\n * @param context - Import context.\n * @param payloadGroups - Private-key group entries from the payload.\n */\nasync function importPrivateKeyWallet(\n context: ImportContext,\n payloadGroups: AccountWalletPrivateKeyGroupEntry[],\n): Promise<void> {\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n\n // Only EVM EOA accounts are supported for now. Non-EVM private keys require\n // Snap-based import routing (ADR-0007), which is not yet implemented. Skip the\n // entire entry so payloads from future clients are accepted without crashing.\n // In the same pass, collect groups whose key is not yet present locally.\n const localWallet = findLocalWalletPrivateKey(context);\n const supportedGroups: AccountWalletPrivateKeyGroupEntry[] = [];\n const missingGroups: AccountWalletPrivateKeyGroupEntry[] = [];\n\n for (const group of payloadGroups) {\n const type = group.value?.type;\n if (type !== undefined && type !== EthAccountType.Eoa) {\n continue;\n }\n\n supportedGroups.push(group);\n\n if (\n !hasLocalGroupPrivateKey(localWallet, group) &&\n group.value !== undefined\n ) {\n missingGroups.push(group);\n }\n }\n\n // Import all missing keys in a single :withController call to avoid\n // triggering multiple `KeyringController:stateChanged` events.\n if (missingGroups.length > 0) {\n await context.messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n // Find the existing simple keyring or create one if this is the\n // first private-key import (e.g. during onboarding).\n const existing = controller.keyrings.find(\n ({ keyring }) => keyring.type === KeyringTypes.simple,\n );\n const { keyringV2 } =\n existing ?? (await controller.addNewKeyring(KeyringTypes.simple));\n\n if (!keyringV2) {\n throw new Error('Simple keyring has no v2 interface');\n }\n\n for (const group of missingGroups) {\n // Safe to assert `group.value` is present because we filtered out groups\n // without a `value` above.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const { privateKey: privateKeyBytes, encoding } = group.value!;\n const privateKey = new TextDecoder().decode(\n decodeBytes(privateKeyBytes),\n );\n const [account] = await keyringV2.createAccounts({\n type: 'private-key:import',\n accountType: EthAccountType.Eoa,\n privateKey,\n encoding,\n });\n\n if (!account) {\n throw new Error('Failed to import private key for account');\n }\n }\n },\n );\n }\n\n // Re-read state once after all imports, then apply metadata to every group\n // that now exists locally.\n for (const group of supportedGroups) {\n const address = parsePayloadGroupId(group.id).subId;\n const localGroupId = toAccountGroupId(localWalletId, address);\n const localGroup = findLocalWalletPrivateKey(context)?.groups[localGroupId];\n if (!localGroup) {\n continue;\n }\n setGroupMetadata(context, localGroup.id, group.metadata);\n }\n}\n\n/**\n * Applies an {@link AccountTreeSnapshot} to the current controller state.\n *\n * The snapshot must already have been validated — typically via\n * {@link AccountTreeSnapshot.deserialize}. For each retained wallet:\n *\n * - `'mnemonic'`: imports the mnemonic when provided and not already present,\n * then applies metadata to all groups.\n * - `'private-key'`: imports each retained group's key when provided and not\n * already present, then applies metadata.\n *\n * @param context - Import context providing state, messenger, and setters.\n * @param snapshot - The validated snapshot to import.\n */\nexport async function importState(\n context: ImportContext,\n snapshot: AccountTreeSnapshot,\n): Promise<void> {\n const payload = snapshot.serialize();\n\n for (const wallet of payload.wallets) {\n if (wallet.type === AccountWalletPayloadType.Mnemonic) {\n await importMnemonicWallet(context, wallet);\n } else {\n await importPrivateKeyWallet(context, wallet.groups);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"import.cjs","sourceRoot":"","sources":["../../src/state/import.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AccountWalletType,\n toAccountGroupId,\n toAccountWalletId,\n toMultichainAccountGroupId,\n} from '@metamask/account-api';\nimport type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport { HdKeyring } from '@metamask/eth-hd-keyring/v2';\nimport { EthAccountType } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\n\nimport type {\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n} from '../types.js';\nimport type {\n AccountWalletEntropyObject,\n AccountWalletKeyringObject,\n} from '../wallet.js';\nimport { isMnemonicWalletObject } from './export.js';\nimport type {\n AccountWalletMnemonicGroupEntry,\n AccountWalletMnemonicPayload,\n AccountWalletPayloadId,\n AccountWalletPrivateKeyGroupEntry,\n} from './payload.js';\nimport {\n AccountWalletPayloadType,\n parsePayloadGroupId,\n toWalletPayloadId,\n} from './payload.js';\nimport type { AccountTreeSnapshot } from './snapshot.js';\nimport { decodeBytes } from './utils.js';\n\n/** Context required by {@link importState}. */\nexport type ImportContext = {\n getState: () => AccountTreeControllerState;\n messenger: AccountTreeControllerMessenger;\n setWalletName: (walletId: AccountWalletId, name: string) => void;\n /** Sets a group name. Implementations must resolve name conflicts automatically. */\n setAccountGroupName: (groupId: AccountGroupId, name: string) => void;\n setAccountGroupPinned: (groupId: AccountGroupId, pinned: boolean) => void;\n setAccountGroupHidden: (groupId: AccountGroupId, hidden: boolean) => void;\n};\n\n/**\n * Searches the local wallet tree for an entropy wallet whose stable payload ID\n * matches `payloadWalletId`. The entropy source ID is derived on-the-fly via\n * `KeyringController:withKeyringV2Unsafe` rather than relying on cached metadata.\n *\n * @param context - Import context.\n * @param payloadWalletId - Payload wallet ID to match against.\n * @returns The matching local entropy wallet, or `undefined` if not found.\n */\nasync function findLocalWalletMnemonicFromPayloadId(\n context: ImportContext,\n payloadWalletId: AccountWalletPayloadId,\n): Promise<AccountWalletEntropyObject | undefined> {\n const wallets = Object.values(context.getState().accountTree.wallets);\n\n for (const wallet of wallets) {\n if (isMnemonicWalletObject(wallet)) {\n const result = await context.messenger.call(\n 'KeyringController:withKeyringV2Unsafe',\n { id: wallet.metadata.entropy.id },\n async ({ keyring }) => {\n const hdKeyring = keyring as HdKeyring;\n\n return toWalletPayloadId(await hdKeyring.toEntropySourceId());\n },\n );\n\n const localPayloadId = result as AccountWalletPayloadId;\n if (localPayloadId === payloadWalletId) {\n return wallet;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Returns the local entropy wallet for the given ID.\n *\n * @param context - Import context.\n * @param id - Local wallet ID.\n * @returns The entropy wallet object.\n * @throws If the wallet is not found or is not an entropy wallet.\n */\nfunction findLocalWalletMnemonicFromId(\n context: ImportContext,\n id: AccountWalletId,\n): AccountWalletEntropyObject {\n const localWallets = context.getState().accountTree.wallets;\n const localWallet = localWallets[id];\n\n if (!localWallet) {\n throw new Error(\n `Failed to import mnemonic wallet: wallet not found after creation`,\n );\n }\n if (!isMnemonicWalletObject(localWallet)) {\n throw new Error(\n `Failed to import mnemonic wallet: wallet is not of type 'mnemonic'`,\n );\n }\n return localWallet;\n}\n\n/**\n * Returns the local simple-keyring wallet, or `undefined` if none exists yet.\n *\n * The private-key wallet ID is static (derived solely from {@link KeyringTypes.simple}),\n * so no runtime argument is needed to locate it.\n *\n * @param context - Import context.\n * @returns The keyring wallet object, or `undefined` if not present in state.\n */\nfunction findLocalWalletPrivateKey(\n context: ImportContext,\n): AccountWalletKeyringObject | undefined {\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n const localWallet = context.getState().accountTree.wallets[localWalletId];\n return localWallet?.type === AccountWalletType.Keyring\n ? localWallet\n : undefined;\n}\n\n/**\n * Returns `true` if the given payload group is already present in the local simple-keyring wallet.\n *\n * @param localWallet - The local simple-keyring wallet, or `undefined` if none exists yet.\n * @param group - The payload group entry to check.\n * @returns Whether the group's account is already tracked locally.\n */\nfunction hasLocalGroupPrivateKey(\n localWallet: AccountWalletKeyringObject | undefined,\n group: AccountWalletPrivateKeyGroupEntry,\n): boolean {\n const address = parsePayloadGroupId(group.id).subId;\n\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n const localGroupId = toAccountGroupId(localWalletId, address);\n const localGroup = localWallet?.groups[localGroupId];\n\n const accountId = getUUIDFromAddressOfNormalAccount(address);\n\n return localGroup?.accounts.some((id) => id === accountId) ?? false;\n}\n\n/**\n * Applies name, pinned, and hidden metadata from a payload group entry to a local group.\n *\n * @param context - Import context providing the metadata setters.\n * @param localGroupId - Local group ID to update.\n * @param payloadGroupMetadata - Metadata from the payload group entry.\n */\nfunction setGroupMetadata(\n context: ImportContext,\n localGroupId: AccountGroupId,\n payloadGroupMetadata: AccountWalletMnemonicGroupEntry['metadata'],\n): void {\n context.setAccountGroupName(localGroupId, payloadGroupMetadata.name);\n context.setAccountGroupPinned(localGroupId, payloadGroupMetadata.pinned);\n context.setAccountGroupHidden(localGroupId, payloadGroupMetadata.hidden);\n}\n\n/**\n * Computes the contiguous ranges of group indices that are present in the payload\n * but absent from the local wallet, so they can be created in batches.\n *\n * @param localWallet - The local entropy wallet to check existing groups against.\n * @param payloadGroups - Ordered group entries from the payload.\n * @returns An array of `[fromGroupIndex, toGroupIndex]` ranges to create.\n */\nfunction getRangesFromPayloadGroups(\n localWallet: AccountWalletEntropyObject,\n payloadGroups: AccountWalletMnemonicGroupEntry[],\n): [number, number][] {\n let rangeIndex: number | undefined;\n const ranges: [number, number][] = [];\n\n // Keep track of the last payload group so we can close the final range if needed.\n let lastPayloadGroup: AccountWalletMnemonicGroupEntry | undefined;\n for (const payloadGroup of payloadGroups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n\n if (localWallet.groups[localGroupId]) {\n if (rangeIndex !== undefined) {\n ranges.push([rangeIndex, payloadGroup.groupIndex - 1]);\n rangeIndex = undefined;\n }\n continue;\n }\n\n rangeIndex ??= payloadGroup.groupIndex;\n lastPayloadGroup = payloadGroup;\n }\n\n if (rangeIndex !== undefined && lastPayloadGroup !== undefined) {\n ranges.push([rangeIndex, lastPayloadGroup.groupIndex]);\n }\n\n return ranges;\n}\n\n/**\n * Applies a mnemonic wallet payload entry to the local state.\n *\n * If no local wallet with the same entropy source ID exists and a mnemonic is\n * present in the payload, a new HD wallet is created via\n * `MultichainAccountService:createMultichainAccountWallet`. Missing groups are\n * created in batches via `MultichainAccountService:createMultichainAccountGroups`.\n * Metadata (name, pinned, hidden) is applied to all groups afterward.\n *\n * @param context - Import context.\n * @param payloadWallet - The mnemonic wallet entry from the payload.\n */\nasync function importMnemonicWallet(\n context: ImportContext,\n payloadWallet: AccountWalletMnemonicPayload,\n): Promise<void> {\n // Find the local wallet with the same entropy source ID if it exists.\n let localWallet = await findLocalWalletMnemonicFromPayloadId(\n context,\n payloadWallet.id,\n );\n\n if (!localWallet) {\n if (!payloadWallet.value) {\n // No mnemonic in payload and wallet doesn't exist locally -- nothing to do.\n return;\n }\n\n // Import the mnemonic as a new HD wallet.\n const mnemonic = decodeBytes(payloadWallet.value);\n const { id } = await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountWallet',\n { type: 'import', mnemonic },\n );\n\n // Event handlers fire synchronously, so the wallet is in the tree now.\n localWallet = findLocalWalletMnemonicFromId(context, id);\n }\n\n context.setWalletName(localWallet.id, payloadWallet.metadata.name);\n\n // Apply metadata to groups that are already present locally before attempting\n // to create missing ones. If createMultichainAccountGroups throws partway\n // through, these groups would otherwise be left without their payload metadata.\n const localExistingGroupIds = new Set(Object.keys(localWallet.groups));\n for (const payloadGroup of payloadWallet.groups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n if (localExistingGroupIds.has(localGroupId)) {\n setGroupMetadata(context, localGroupId, payloadGroup.metadata);\n }\n }\n\n for (const range of getRangesFromPayloadGroups(\n localWallet,\n payloadWallet.groups,\n )) {\n await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountGroups',\n {\n entropySource: localWallet.metadata.entropy.id,\n fromGroupIndex: range[0],\n toGroupIndex: range[1],\n },\n );\n }\n\n // Re-read wallet after groups creation.\n localWallet = findLocalWalletMnemonicFromId(context, localWallet.id);\n\n // Apply metadata to newly created groups. Skip groups that were already\n // handled above, and guard against groups that failed to be created so a\n // partial failure doesn't throw and abort the rest of the snapshot import.\n for (const payloadGroup of payloadWallet.groups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n if (\n localExistingGroupIds.has(localGroupId) ||\n !localWallet.groups[localGroupId]\n ) {\n continue;\n }\n setGroupMetadata(context, localGroupId, payloadGroup.metadata);\n }\n}\n\n/**\n * Applies private-key wallet group entries from the payload to the local state.\n *\n * For each group the account address is derived from the payload group ID. If the\n * account does not yet exist locally and a private key is provided, it is imported\n * via `KeyringController:withKeyringV2` using the `'private-key:import'` constructor.\n * Metadata (name, pinned, hidden) is then applied to the local group.\n *\n * @param context - Import context.\n * @param payloadGroups - Private-key group entries from the payload.\n */\nasync function importPrivateKeyWallet(\n context: ImportContext,\n payloadGroups: AccountWalletPrivateKeyGroupEntry[],\n): Promise<void> {\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n\n // Only EVM EOA accounts are supported for now. Non-EVM private keys require\n // Snap-based import routing (ADR-0007), which is not yet implemented. Skip the\n // entire entry so payloads from future clients are accepted without crashing.\n // In the same pass, collect groups whose key is not yet present locally.\n const localWallet = findLocalWalletPrivateKey(context);\n const supportedGroups: AccountWalletPrivateKeyGroupEntry[] = [];\n const missingGroups: AccountWalletPrivateKeyGroupEntry[] = [];\n\n for (const group of payloadGroups) {\n const type = group.value?.type;\n if (type !== undefined && type !== EthAccountType.Eoa) {\n continue;\n }\n\n supportedGroups.push(group);\n\n if (\n !hasLocalGroupPrivateKey(localWallet, group) &&\n group.value !== undefined\n ) {\n missingGroups.push(group);\n }\n }\n\n // Import all missing keys in a single :withController call to avoid\n // triggering multiple `KeyringController:stateChanged` events.\n if (missingGroups.length > 0) {\n await context.messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n // Find the existing simple keyring or create one if this is the\n // first private-key import (e.g. during onboarding).\n const existing = controller.keyrings.find(\n ({ keyring }) => keyring.type === KeyringTypes.simple,\n );\n const { keyringV2 } =\n existing ?? (await controller.addNewKeyring(KeyringTypes.simple));\n\n if (!keyringV2) {\n throw new Error('Simple keyring has no v2 interface');\n }\n\n for (const group of missingGroups) {\n // Safe to assert `group.value` is present because we filtered out groups\n // without a `value` above.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const { privateKey: privateKeyBytes, encoding } = group.value!;\n const privateKey = new TextDecoder().decode(\n decodeBytes(privateKeyBytes),\n );\n const [account] = await keyringV2.createAccounts({\n type: 'private-key:import',\n accountType: EthAccountType.Eoa,\n privateKey,\n encoding,\n });\n\n if (!account) {\n throw new Error('Failed to import private key for account');\n }\n }\n },\n );\n }\n\n // Re-read state once after all imports, then apply metadata to every group\n // that now exists locally.\n for (const group of supportedGroups) {\n const address = parsePayloadGroupId(group.id).subId;\n const localGroupId = toAccountGroupId(localWalletId, address);\n const localGroup = findLocalWalletPrivateKey(context)?.groups[localGroupId];\n if (!localGroup) {\n continue;\n }\n setGroupMetadata(context, localGroup.id, group.metadata);\n }\n}\n\n/**\n * Applies an {@link AccountTreeSnapshot} to the current controller state.\n *\n * The snapshot must already have been validated — typically via\n * {@link AccountTreeSnapshot.deserialize}. For each retained wallet:\n *\n * - `'mnemonic'`: imports the mnemonic when provided and not already present,\n * then applies metadata to all groups.\n * - `'private-key'`: imports each retained group's key when provided and not\n * already present, then applies metadata.\n *\n * @param context - Import context providing state, messenger, and setters.\n * @param snapshot - The validated snapshot to import.\n */\nexport async function importState(\n context: ImportContext,\n snapshot: AccountTreeSnapshot,\n): Promise<void> {\n const payload = snapshot.serialize();\n\n for (const wallet of payload.wallets) {\n if (wallet.type === AccountWalletPayloadType.Mnemonic) {\n await importMnemonicWallet(context, wallet);\n } else {\n await importPrivateKeyWallet(context, wallet.groups);\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.d.cts","sourceRoot":"","sources":["../../src/state/import.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,8BAA8B;AAM7E,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC3B,qBAAoB;AAiBrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAsB;AAGzD,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,0BAA0B,CAAC;IAC3C,SAAS,EAAE,8BAA8B,CAAC;IAC1C,aAAa,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,oFAAoF;IACpF,mBAAmB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1E,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3E,CAAC;
|
|
1
|
+
{"version":3,"file":"import.d.cts","sourceRoot":"","sources":["../../src/state/import.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,8BAA8B;AAM7E,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC3B,qBAAoB;AAiBrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAsB;AAGzD,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,0BAA0B,CAAC;IAC3C,SAAS,EAAE,8BAA8B,CAAC;IAC1C,aAAa,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,oFAAoF;IACpF,mBAAmB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1E,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3E,CAAC;AAyWF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.d.mts","sourceRoot":"","sources":["../../src/state/import.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,8BAA8B;AAM7E,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC3B,qBAAoB;AAiBrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAsB;AAGzD,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,0BAA0B,CAAC;IAC3C,SAAS,EAAE,8BAA8B,CAAC;IAC1C,aAAa,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,oFAAoF;IACpF,mBAAmB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1E,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3E,CAAC;
|
|
1
|
+
{"version":3,"file":"import.d.mts","sourceRoot":"","sources":["../../src/state/import.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,8BAA8B;AAM7E,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC3B,qBAAoB;AAiBrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAsB;AAGzD,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,0BAA0B,CAAC;IAC3C,SAAS,EAAE,8BAA8B,CAAC;IAC1C,aAAa,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,oFAAoF;IACpF,mBAAmB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1E,qBAAqB,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3E,CAAC;AAyWF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
package/dist/state/import.mjs
CHANGED
|
@@ -89,11 +89,9 @@ function hasLocalGroupPrivateKey(localWallet, group) {
|
|
|
89
89
|
* @param payloadGroupMetadata - Metadata from the payload group entry.
|
|
90
90
|
*/
|
|
91
91
|
function setGroupMetadata(context, localGroupId, payloadGroupMetadata) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
context.setAccountGroupHidden(localGroupId, payloadGroupMetadata.hidden);
|
|
96
|
-
}
|
|
92
|
+
context.setAccountGroupName(localGroupId, payloadGroupMetadata.name);
|
|
93
|
+
context.setAccountGroupPinned(localGroupId, payloadGroupMetadata.pinned);
|
|
94
|
+
context.setAccountGroupHidden(localGroupId, payloadGroupMetadata.hidden);
|
|
97
95
|
}
|
|
98
96
|
/**
|
|
99
97
|
* Computes the contiguous ranges of group indices that are present in the payload
|
|
@@ -151,9 +149,7 @@ async function importMnemonicWallet(context, payloadWallet) {
|
|
|
151
149
|
// Event handlers fire synchronously, so the wallet is in the tree now.
|
|
152
150
|
localWallet = findLocalWalletMnemonicFromId(context, id);
|
|
153
151
|
}
|
|
154
|
-
|
|
155
|
-
context.setWalletName(localWallet.id, payloadWallet.metadata.name);
|
|
156
|
-
}
|
|
152
|
+
context.setWalletName(localWallet.id, payloadWallet.metadata.name);
|
|
157
153
|
// Apply metadata to groups that are already present locally before attempting
|
|
158
154
|
// to create missing ones. If createMultichainAccountGroups throws partway
|
|
159
155
|
// through, these groups would otherwise be left without their payload metadata.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.mjs","sourceRoot":"","sources":["../../src/state/import.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AccountWalletType,\n toAccountGroupId,\n toAccountWalletId,\n toMultichainAccountGroupId,\n} from '@metamask/account-api';\nimport type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport { HdKeyring } from '@metamask/eth-hd-keyring/v2';\nimport { EthAccountType } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\n\nimport type {\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n} from '../types.js';\nimport type {\n AccountWalletEntropyObject,\n AccountWalletKeyringObject,\n} from '../wallet.js';\nimport { isMnemonicWalletObject } from './export.js';\nimport type {\n AccountWalletMnemonicGroupEntry,\n AccountWalletMnemonicPayload,\n AccountWalletPayloadId,\n AccountWalletPrivateKeyGroupEntry,\n} from './payload.js';\nimport {\n AccountWalletPayloadType,\n parsePayloadGroupId,\n toWalletPayloadId,\n} from './payload.js';\nimport type { AccountTreeSnapshot } from './snapshot.js';\nimport { decodeBytes } from './utils.js';\n\n/** Context required by {@link importState}. */\nexport type ImportContext = {\n getState: () => AccountTreeControllerState;\n messenger: AccountTreeControllerMessenger;\n setWalletName: (walletId: AccountWalletId, name: string) => void;\n /** Sets a group name. Implementations must resolve name conflicts automatically. */\n setAccountGroupName: (groupId: AccountGroupId, name: string) => void;\n setAccountGroupPinned: (groupId: AccountGroupId, pinned: boolean) => void;\n setAccountGroupHidden: (groupId: AccountGroupId, hidden: boolean) => void;\n};\n\n/**\n * Searches the local wallet tree for an entropy wallet whose stable payload ID\n * matches `payloadWalletId`. The entropy source ID is derived on-the-fly via\n * `KeyringController:withKeyringV2Unsafe` rather than relying on cached metadata.\n *\n * @param context - Import context.\n * @param payloadWalletId - Payload wallet ID to match against.\n * @returns The matching local entropy wallet, or `undefined` if not found.\n */\nasync function findLocalWalletMnemonicFromPayloadId(\n context: ImportContext,\n payloadWalletId: AccountWalletPayloadId,\n): Promise<AccountWalletEntropyObject | undefined> {\n const wallets = Object.values(context.getState().accountTree.wallets);\n\n for (const wallet of wallets) {\n if (isMnemonicWalletObject(wallet)) {\n const result = await context.messenger.call(\n 'KeyringController:withKeyringV2Unsafe',\n { id: wallet.metadata.entropy.id },\n async ({ keyring }) => {\n const hdKeyring = keyring as HdKeyring;\n\n return toWalletPayloadId(await hdKeyring.toEntropySourceId());\n },\n );\n\n const localPayloadId = result as AccountWalletPayloadId;\n if (localPayloadId === payloadWalletId) {\n return wallet;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Returns the local entropy wallet for the given ID.\n *\n * @param context - Import context.\n * @param id - Local wallet ID.\n * @returns The entropy wallet object.\n * @throws If the wallet is not found or is not an entropy wallet.\n */\nfunction findLocalWalletMnemonicFromId(\n context: ImportContext,\n id: AccountWalletId,\n): AccountWalletEntropyObject {\n const localWallets = context.getState().accountTree.wallets;\n const localWallet = localWallets[id];\n\n if (!localWallet) {\n throw new Error(\n `Failed to import mnemonic wallet: wallet not found after creation`,\n );\n }\n if (!isMnemonicWalletObject(localWallet)) {\n throw new Error(\n `Failed to import mnemonic wallet: wallet is not of type 'mnemonic'`,\n );\n }\n return localWallet;\n}\n\n/**\n * Returns the local simple-keyring wallet, or `undefined` if none exists yet.\n *\n * The private-key wallet ID is static (derived solely from {@link KeyringTypes.simple}),\n * so no runtime argument is needed to locate it.\n *\n * @param context - Import context.\n * @returns The keyring wallet object, or `undefined` if not present in state.\n */\nfunction findLocalWalletPrivateKey(\n context: ImportContext,\n): AccountWalletKeyringObject | undefined {\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n const localWallet = context.getState().accountTree.wallets[localWalletId];\n return localWallet?.type === AccountWalletType.Keyring\n ? localWallet\n : undefined;\n}\n\n/**\n * Returns `true` if the given payload group is already present in the local simple-keyring wallet.\n *\n * @param localWallet - The local simple-keyring wallet, or `undefined` if none exists yet.\n * @param group - The payload group entry to check.\n * @returns Whether the group's account is already tracked locally.\n */\nfunction hasLocalGroupPrivateKey(\n localWallet: AccountWalletKeyringObject | undefined,\n group: AccountWalletPrivateKeyGroupEntry,\n): boolean {\n const address = parsePayloadGroupId(group.id).subId;\n\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n const localGroupId = toAccountGroupId(localWalletId, address);\n const localGroup = localWallet?.groups[localGroupId];\n\n const accountId = getUUIDFromAddressOfNormalAccount(address);\n\n return localGroup?.accounts.some((id) => id === accountId) ?? false;\n}\n\n/**\n * Applies name, pinned, and hidden metadata from a payload group entry to a local group.\n *\n * @param context - Import context providing the metadata setters.\n * @param localGroupId - Local group ID to update.\n * @param payloadGroupMetadata - Metadata from the payload group entry.\n */\nfunction setGroupMetadata(\n context: ImportContext,\n localGroupId: AccountGroupId,\n payloadGroupMetadata: AccountWalletMnemonicGroupEntry['metadata'],\n): void {\n if (payloadGroupMetadata) {\n context.setAccountGroupName(localGroupId, payloadGroupMetadata.name);\n context.setAccountGroupPinned(localGroupId, payloadGroupMetadata.pinned);\n context.setAccountGroupHidden(localGroupId, payloadGroupMetadata.hidden);\n }\n}\n\n/**\n * Computes the contiguous ranges of group indices that are present in the payload\n * but absent from the local wallet, so they can be created in batches.\n *\n * @param localWallet - The local entropy wallet to check existing groups against.\n * @param payloadGroups - Ordered group entries from the payload.\n * @returns An array of `[fromGroupIndex, toGroupIndex]` ranges to create.\n */\nfunction getRangesFromPayloadGroups(\n localWallet: AccountWalletEntropyObject,\n payloadGroups: AccountWalletMnemonicGroupEntry[],\n): [number, number][] {\n let rangeIndex: number | undefined;\n const ranges: [number, number][] = [];\n\n // Keep track of the last payload group so we can close the final range if needed.\n let lastPayloadGroup: AccountWalletMnemonicGroupEntry | undefined;\n for (const payloadGroup of payloadGroups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n\n if (localWallet.groups[localGroupId]) {\n if (rangeIndex !== undefined) {\n ranges.push([rangeIndex, payloadGroup.groupIndex - 1]);\n rangeIndex = undefined;\n }\n continue;\n }\n\n rangeIndex ??= payloadGroup.groupIndex;\n lastPayloadGroup = payloadGroup;\n }\n\n if (rangeIndex !== undefined && lastPayloadGroup !== undefined) {\n ranges.push([rangeIndex, lastPayloadGroup.groupIndex]);\n }\n\n return ranges;\n}\n\n/**\n * Applies a mnemonic wallet payload entry to the local state.\n *\n * If no local wallet with the same entropy source ID exists and a mnemonic is\n * present in the payload, a new HD wallet is created via\n * `MultichainAccountService:createMultichainAccountWallet`. Missing groups are\n * created in batches via `MultichainAccountService:createMultichainAccountGroups`.\n * Metadata (name, pinned, hidden) is applied to all groups afterward.\n *\n * @param context - Import context.\n * @param payloadWallet - The mnemonic wallet entry from the payload.\n */\nasync function importMnemonicWallet(\n context: ImportContext,\n payloadWallet: AccountWalletMnemonicPayload,\n): Promise<void> {\n // Find the local wallet with the same entropy source ID if it exists.\n let localWallet = await findLocalWalletMnemonicFromPayloadId(\n context,\n payloadWallet.id,\n );\n\n if (!localWallet) {\n if (!payloadWallet.value) {\n // No mnemonic in payload and wallet doesn't exist locally -- nothing to do.\n return;\n }\n\n // Import the mnemonic as a new HD wallet.\n const mnemonic = decodeBytes(payloadWallet.value);\n const { id } = await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountWallet',\n { type: 'import', mnemonic },\n );\n\n // Event handlers fire synchronously, so the wallet is in the tree now.\n localWallet = findLocalWalletMnemonicFromId(context, id);\n }\n\n if (payloadWallet.metadata) {\n context.setWalletName(localWallet.id, payloadWallet.metadata.name);\n }\n\n // Apply metadata to groups that are already present locally before attempting\n // to create missing ones. If createMultichainAccountGroups throws partway\n // through, these groups would otherwise be left without their payload metadata.\n const localExistingGroupIds = new Set(Object.keys(localWallet.groups));\n for (const payloadGroup of payloadWallet.groups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n if (localExistingGroupIds.has(localGroupId)) {\n setGroupMetadata(context, localGroupId, payloadGroup.metadata);\n }\n }\n\n for (const range of getRangesFromPayloadGroups(\n localWallet,\n payloadWallet.groups,\n )) {\n await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountGroups',\n {\n entropySource: localWallet.metadata.entropy.id,\n fromGroupIndex: range[0],\n toGroupIndex: range[1],\n },\n );\n }\n\n // Re-read wallet after groups creation.\n localWallet = findLocalWalletMnemonicFromId(context, localWallet.id);\n\n // Apply metadata to newly created groups. Skip groups that were already\n // handled above, and guard against groups that failed to be created so a\n // partial failure doesn't throw and abort the rest of the snapshot import.\n for (const payloadGroup of payloadWallet.groups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n if (\n localExistingGroupIds.has(localGroupId) ||\n !localWallet.groups[localGroupId]\n ) {\n continue;\n }\n setGroupMetadata(context, localGroupId, payloadGroup.metadata);\n }\n}\n\n/**\n * Applies private-key wallet group entries from the payload to the local state.\n *\n * For each group the account address is derived from the payload group ID. If the\n * account does not yet exist locally and a private key is provided, it is imported\n * via `KeyringController:withKeyringV2` using the `'private-key:import'` constructor.\n * Metadata (name, pinned, hidden) is then applied to the local group.\n *\n * @param context - Import context.\n * @param payloadGroups - Private-key group entries from the payload.\n */\nasync function importPrivateKeyWallet(\n context: ImportContext,\n payloadGroups: AccountWalletPrivateKeyGroupEntry[],\n): Promise<void> {\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n\n // Only EVM EOA accounts are supported for now. Non-EVM private keys require\n // Snap-based import routing (ADR-0007), which is not yet implemented. Skip the\n // entire entry so payloads from future clients are accepted without crashing.\n // In the same pass, collect groups whose key is not yet present locally.\n const localWallet = findLocalWalletPrivateKey(context);\n const supportedGroups: AccountWalletPrivateKeyGroupEntry[] = [];\n const missingGroups: AccountWalletPrivateKeyGroupEntry[] = [];\n\n for (const group of payloadGroups) {\n const type = group.value?.type;\n if (type !== undefined && type !== EthAccountType.Eoa) {\n continue;\n }\n\n supportedGroups.push(group);\n\n if (\n !hasLocalGroupPrivateKey(localWallet, group) &&\n group.value !== undefined\n ) {\n missingGroups.push(group);\n }\n }\n\n // Import all missing keys in a single :withController call to avoid\n // triggering multiple `KeyringController:stateChanged` events.\n if (missingGroups.length > 0) {\n await context.messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n // Find the existing simple keyring or create one if this is the\n // first private-key import (e.g. during onboarding).\n const existing = controller.keyrings.find(\n ({ keyring }) => keyring.type === KeyringTypes.simple,\n );\n const { keyringV2 } =\n existing ?? (await controller.addNewKeyring(KeyringTypes.simple));\n\n if (!keyringV2) {\n throw new Error('Simple keyring has no v2 interface');\n }\n\n for (const group of missingGroups) {\n // Safe to assert `group.value` is present because we filtered out groups\n // without a `value` above.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const { privateKey: privateKeyBytes, encoding } = group.value!;\n const privateKey = new TextDecoder().decode(\n decodeBytes(privateKeyBytes),\n );\n const [account] = await keyringV2.createAccounts({\n type: 'private-key:import',\n accountType: EthAccountType.Eoa,\n privateKey,\n encoding,\n });\n\n if (!account) {\n throw new Error('Failed to import private key for account');\n }\n }\n },\n );\n }\n\n // Re-read state once after all imports, then apply metadata to every group\n // that now exists locally.\n for (const group of supportedGroups) {\n const address = parsePayloadGroupId(group.id).subId;\n const localGroupId = toAccountGroupId(localWalletId, address);\n const localGroup = findLocalWalletPrivateKey(context)?.groups[localGroupId];\n if (!localGroup) {\n continue;\n }\n setGroupMetadata(context, localGroup.id, group.metadata);\n }\n}\n\n/**\n * Applies an {@link AccountTreeSnapshot} to the current controller state.\n *\n * The snapshot must already have been validated — typically via\n * {@link AccountTreeSnapshot.deserialize}. For each retained wallet:\n *\n * - `'mnemonic'`: imports the mnemonic when provided and not already present,\n * then applies metadata to all groups.\n * - `'private-key'`: imports each retained group's key when provided and not\n * already present, then applies metadata.\n *\n * @param context - Import context providing state, messenger, and setters.\n * @param snapshot - The validated snapshot to import.\n */\nexport async function importState(\n context: ImportContext,\n snapshot: AccountTreeSnapshot,\n): Promise<void> {\n const payload = snapshot.serialize();\n\n for (const wallet of payload.wallets) {\n if (wallet.type === AccountWalletPayloadType.Mnemonic) {\n await importMnemonicWallet(context, wallet);\n } else {\n await importPrivateKeyWallet(context, wallet.groups);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"import.mjs","sourceRoot":"","sources":["../../src/state/import.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AccountWalletType,\n toAccountGroupId,\n toAccountWalletId,\n toMultichainAccountGroupId,\n} from '@metamask/account-api';\nimport type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport { HdKeyring } from '@metamask/eth-hd-keyring/v2';\nimport { EthAccountType } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\n\nimport type {\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n} from '../types.js';\nimport type {\n AccountWalletEntropyObject,\n AccountWalletKeyringObject,\n} from '../wallet.js';\nimport { isMnemonicWalletObject } from './export.js';\nimport type {\n AccountWalletMnemonicGroupEntry,\n AccountWalletMnemonicPayload,\n AccountWalletPayloadId,\n AccountWalletPrivateKeyGroupEntry,\n} from './payload.js';\nimport {\n AccountWalletPayloadType,\n parsePayloadGroupId,\n toWalletPayloadId,\n} from './payload.js';\nimport type { AccountTreeSnapshot } from './snapshot.js';\nimport { decodeBytes } from './utils.js';\n\n/** Context required by {@link importState}. */\nexport type ImportContext = {\n getState: () => AccountTreeControllerState;\n messenger: AccountTreeControllerMessenger;\n setWalletName: (walletId: AccountWalletId, name: string) => void;\n /** Sets a group name. Implementations must resolve name conflicts automatically. */\n setAccountGroupName: (groupId: AccountGroupId, name: string) => void;\n setAccountGroupPinned: (groupId: AccountGroupId, pinned: boolean) => void;\n setAccountGroupHidden: (groupId: AccountGroupId, hidden: boolean) => void;\n};\n\n/**\n * Searches the local wallet tree for an entropy wallet whose stable payload ID\n * matches `payloadWalletId`. The entropy source ID is derived on-the-fly via\n * `KeyringController:withKeyringV2Unsafe` rather than relying on cached metadata.\n *\n * @param context - Import context.\n * @param payloadWalletId - Payload wallet ID to match against.\n * @returns The matching local entropy wallet, or `undefined` if not found.\n */\nasync function findLocalWalletMnemonicFromPayloadId(\n context: ImportContext,\n payloadWalletId: AccountWalletPayloadId,\n): Promise<AccountWalletEntropyObject | undefined> {\n const wallets = Object.values(context.getState().accountTree.wallets);\n\n for (const wallet of wallets) {\n if (isMnemonicWalletObject(wallet)) {\n const result = await context.messenger.call(\n 'KeyringController:withKeyringV2Unsafe',\n { id: wallet.metadata.entropy.id },\n async ({ keyring }) => {\n const hdKeyring = keyring as HdKeyring;\n\n return toWalletPayloadId(await hdKeyring.toEntropySourceId());\n },\n );\n\n const localPayloadId = result as AccountWalletPayloadId;\n if (localPayloadId === payloadWalletId) {\n return wallet;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Returns the local entropy wallet for the given ID.\n *\n * @param context - Import context.\n * @param id - Local wallet ID.\n * @returns The entropy wallet object.\n * @throws If the wallet is not found or is not an entropy wallet.\n */\nfunction findLocalWalletMnemonicFromId(\n context: ImportContext,\n id: AccountWalletId,\n): AccountWalletEntropyObject {\n const localWallets = context.getState().accountTree.wallets;\n const localWallet = localWallets[id];\n\n if (!localWallet) {\n throw new Error(\n `Failed to import mnemonic wallet: wallet not found after creation`,\n );\n }\n if (!isMnemonicWalletObject(localWallet)) {\n throw new Error(\n `Failed to import mnemonic wallet: wallet is not of type 'mnemonic'`,\n );\n }\n return localWallet;\n}\n\n/**\n * Returns the local simple-keyring wallet, or `undefined` if none exists yet.\n *\n * The private-key wallet ID is static (derived solely from {@link KeyringTypes.simple}),\n * so no runtime argument is needed to locate it.\n *\n * @param context - Import context.\n * @returns The keyring wallet object, or `undefined` if not present in state.\n */\nfunction findLocalWalletPrivateKey(\n context: ImportContext,\n): AccountWalletKeyringObject | undefined {\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n const localWallet = context.getState().accountTree.wallets[localWalletId];\n return localWallet?.type === AccountWalletType.Keyring\n ? localWallet\n : undefined;\n}\n\n/**\n * Returns `true` if the given payload group is already present in the local simple-keyring wallet.\n *\n * @param localWallet - The local simple-keyring wallet, or `undefined` if none exists yet.\n * @param group - The payload group entry to check.\n * @returns Whether the group's account is already tracked locally.\n */\nfunction hasLocalGroupPrivateKey(\n localWallet: AccountWalletKeyringObject | undefined,\n group: AccountWalletPrivateKeyGroupEntry,\n): boolean {\n const address = parsePayloadGroupId(group.id).subId;\n\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n const localGroupId = toAccountGroupId(localWalletId, address);\n const localGroup = localWallet?.groups[localGroupId];\n\n const accountId = getUUIDFromAddressOfNormalAccount(address);\n\n return localGroup?.accounts.some((id) => id === accountId) ?? false;\n}\n\n/**\n * Applies name, pinned, and hidden metadata from a payload group entry to a local group.\n *\n * @param context - Import context providing the metadata setters.\n * @param localGroupId - Local group ID to update.\n * @param payloadGroupMetadata - Metadata from the payload group entry.\n */\nfunction setGroupMetadata(\n context: ImportContext,\n localGroupId: AccountGroupId,\n payloadGroupMetadata: AccountWalletMnemonicGroupEntry['metadata'],\n): void {\n context.setAccountGroupName(localGroupId, payloadGroupMetadata.name);\n context.setAccountGroupPinned(localGroupId, payloadGroupMetadata.pinned);\n context.setAccountGroupHidden(localGroupId, payloadGroupMetadata.hidden);\n}\n\n/**\n * Computes the contiguous ranges of group indices that are present in the payload\n * but absent from the local wallet, so they can be created in batches.\n *\n * @param localWallet - The local entropy wallet to check existing groups against.\n * @param payloadGroups - Ordered group entries from the payload.\n * @returns An array of `[fromGroupIndex, toGroupIndex]` ranges to create.\n */\nfunction getRangesFromPayloadGroups(\n localWallet: AccountWalletEntropyObject,\n payloadGroups: AccountWalletMnemonicGroupEntry[],\n): [number, number][] {\n let rangeIndex: number | undefined;\n const ranges: [number, number][] = [];\n\n // Keep track of the last payload group so we can close the final range if needed.\n let lastPayloadGroup: AccountWalletMnemonicGroupEntry | undefined;\n for (const payloadGroup of payloadGroups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n\n if (localWallet.groups[localGroupId]) {\n if (rangeIndex !== undefined) {\n ranges.push([rangeIndex, payloadGroup.groupIndex - 1]);\n rangeIndex = undefined;\n }\n continue;\n }\n\n rangeIndex ??= payloadGroup.groupIndex;\n lastPayloadGroup = payloadGroup;\n }\n\n if (rangeIndex !== undefined && lastPayloadGroup !== undefined) {\n ranges.push([rangeIndex, lastPayloadGroup.groupIndex]);\n }\n\n return ranges;\n}\n\n/**\n * Applies a mnemonic wallet payload entry to the local state.\n *\n * If no local wallet with the same entropy source ID exists and a mnemonic is\n * present in the payload, a new HD wallet is created via\n * `MultichainAccountService:createMultichainAccountWallet`. Missing groups are\n * created in batches via `MultichainAccountService:createMultichainAccountGroups`.\n * Metadata (name, pinned, hidden) is applied to all groups afterward.\n *\n * @param context - Import context.\n * @param payloadWallet - The mnemonic wallet entry from the payload.\n */\nasync function importMnemonicWallet(\n context: ImportContext,\n payloadWallet: AccountWalletMnemonicPayload,\n): Promise<void> {\n // Find the local wallet with the same entropy source ID if it exists.\n let localWallet = await findLocalWalletMnemonicFromPayloadId(\n context,\n payloadWallet.id,\n );\n\n if (!localWallet) {\n if (!payloadWallet.value) {\n // No mnemonic in payload and wallet doesn't exist locally -- nothing to do.\n return;\n }\n\n // Import the mnemonic as a new HD wallet.\n const mnemonic = decodeBytes(payloadWallet.value);\n const { id } = await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountWallet',\n { type: 'import', mnemonic },\n );\n\n // Event handlers fire synchronously, so the wallet is in the tree now.\n localWallet = findLocalWalletMnemonicFromId(context, id);\n }\n\n context.setWalletName(localWallet.id, payloadWallet.metadata.name);\n\n // Apply metadata to groups that are already present locally before attempting\n // to create missing ones. If createMultichainAccountGroups throws partway\n // through, these groups would otherwise be left without their payload metadata.\n const localExistingGroupIds = new Set(Object.keys(localWallet.groups));\n for (const payloadGroup of payloadWallet.groups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n if (localExistingGroupIds.has(localGroupId)) {\n setGroupMetadata(context, localGroupId, payloadGroup.metadata);\n }\n }\n\n for (const range of getRangesFromPayloadGroups(\n localWallet,\n payloadWallet.groups,\n )) {\n await context.messenger.call(\n 'MultichainAccountService:createMultichainAccountGroups',\n {\n entropySource: localWallet.metadata.entropy.id,\n fromGroupIndex: range[0],\n toGroupIndex: range[1],\n },\n );\n }\n\n // Re-read wallet after groups creation.\n localWallet = findLocalWalletMnemonicFromId(context, localWallet.id);\n\n // Apply metadata to newly created groups. Skip groups that were already\n // handled above, and guard against groups that failed to be created so a\n // partial failure doesn't throw and abort the rest of the snapshot import.\n for (const payloadGroup of payloadWallet.groups) {\n const localGroupId = toMultichainAccountGroupId(\n localWallet.id,\n payloadGroup.groupIndex,\n );\n if (\n localExistingGroupIds.has(localGroupId) ||\n !localWallet.groups[localGroupId]\n ) {\n continue;\n }\n setGroupMetadata(context, localGroupId, payloadGroup.metadata);\n }\n}\n\n/**\n * Applies private-key wallet group entries from the payload to the local state.\n *\n * For each group the account address is derived from the payload group ID. If the\n * account does not yet exist locally and a private key is provided, it is imported\n * via `KeyringController:withKeyringV2` using the `'private-key:import'` constructor.\n * Metadata (name, pinned, hidden) is then applied to the local group.\n *\n * @param context - Import context.\n * @param payloadGroups - Private-key group entries from the payload.\n */\nasync function importPrivateKeyWallet(\n context: ImportContext,\n payloadGroups: AccountWalletPrivateKeyGroupEntry[],\n): Promise<void> {\n const localWalletId = toAccountWalletId(\n AccountWalletType.Keyring,\n KeyringTypes.simple,\n );\n\n // Only EVM EOA accounts are supported for now. Non-EVM private keys require\n // Snap-based import routing (ADR-0007), which is not yet implemented. Skip the\n // entire entry so payloads from future clients are accepted without crashing.\n // In the same pass, collect groups whose key is not yet present locally.\n const localWallet = findLocalWalletPrivateKey(context);\n const supportedGroups: AccountWalletPrivateKeyGroupEntry[] = [];\n const missingGroups: AccountWalletPrivateKeyGroupEntry[] = [];\n\n for (const group of payloadGroups) {\n const type = group.value?.type;\n if (type !== undefined && type !== EthAccountType.Eoa) {\n continue;\n }\n\n supportedGroups.push(group);\n\n if (\n !hasLocalGroupPrivateKey(localWallet, group) &&\n group.value !== undefined\n ) {\n missingGroups.push(group);\n }\n }\n\n // Import all missing keys in a single :withController call to avoid\n // triggering multiple `KeyringController:stateChanged` events.\n if (missingGroups.length > 0) {\n await context.messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n // Find the existing simple keyring or create one if this is the\n // first private-key import (e.g. during onboarding).\n const existing = controller.keyrings.find(\n ({ keyring }) => keyring.type === KeyringTypes.simple,\n );\n const { keyringV2 } =\n existing ?? (await controller.addNewKeyring(KeyringTypes.simple));\n\n if (!keyringV2) {\n throw new Error('Simple keyring has no v2 interface');\n }\n\n for (const group of missingGroups) {\n // Safe to assert `group.value` is present because we filtered out groups\n // without a `value` above.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const { privateKey: privateKeyBytes, encoding } = group.value!;\n const privateKey = new TextDecoder().decode(\n decodeBytes(privateKeyBytes),\n );\n const [account] = await keyringV2.createAccounts({\n type: 'private-key:import',\n accountType: EthAccountType.Eoa,\n privateKey,\n encoding,\n });\n\n if (!account) {\n throw new Error('Failed to import private key for account');\n }\n }\n },\n );\n }\n\n // Re-read state once after all imports, then apply metadata to every group\n // that now exists locally.\n for (const group of supportedGroups) {\n const address = parsePayloadGroupId(group.id).subId;\n const localGroupId = toAccountGroupId(localWalletId, address);\n const localGroup = findLocalWalletPrivateKey(context)?.groups[localGroupId];\n if (!localGroup) {\n continue;\n }\n setGroupMetadata(context, localGroup.id, group.metadata);\n }\n}\n\n/**\n * Applies an {@link AccountTreeSnapshot} to the current controller state.\n *\n * The snapshot must already have been validated — typically via\n * {@link AccountTreeSnapshot.deserialize}. For each retained wallet:\n *\n * - `'mnemonic'`: imports the mnemonic when provided and not already present,\n * then applies metadata to all groups.\n * - `'private-key'`: imports each retained group's key when provided and not\n * already present, then applies metadata.\n *\n * @param context - Import context providing state, messenger, and setters.\n * @param snapshot - The validated snapshot to import.\n */\nexport async function importState(\n context: ImportContext,\n snapshot: AccountTreeSnapshot,\n): Promise<void> {\n const payload = snapshot.serialize();\n\n for (const wallet of payload.wallets) {\n if (wallet.type === AccountWalletPayloadType.Mnemonic) {\n await importMnemonicWallet(context, wallet);\n } else {\n await importPrivateKeyWallet(context, wallet.groups);\n }\n }\n}\n"]}
|
package/dist/state/payload.cjs
CHANGED
|
@@ -84,12 +84,12 @@ const AccountWalletPrivateKeyValueStruct = (0, superstruct_1.object)({
|
|
|
84
84
|
const AccountWalletMnemonicGroupEntryStruct = (0, superstruct_1.object)({
|
|
85
85
|
id: AccountGroupPayloadIdStruct,
|
|
86
86
|
groupIndex: (0, superstruct_1.integer)(),
|
|
87
|
-
metadata:
|
|
87
|
+
metadata: AccountWalletGroupPayloadMetadataStruct,
|
|
88
88
|
});
|
|
89
89
|
const AccountWalletPrivateKeyGroupEntryStruct = (0, superstruct_1.object)({
|
|
90
90
|
id: AccountGroupPayloadIdStruct,
|
|
91
91
|
value: (0, superstruct_1.exactOptional)(AccountWalletPrivateKeyValueStruct),
|
|
92
|
-
metadata:
|
|
92
|
+
metadata: AccountWalletGroupPayloadMetadataStruct,
|
|
93
93
|
});
|
|
94
94
|
// The `groups` array in a mnemonic wallet payload must have contiguous group indices starting at 0.
|
|
95
95
|
const AccountWalletMnemonicGroupsStruct = (0, superstruct_1.refine)((0, superstruct_1.array)(AccountWalletMnemonicGroupEntryStruct), 'contiguous-group-indices', (groups) => {
|
|
@@ -109,13 +109,13 @@ const AccountWalletMnemonicPayloadStruct = (0, superstruct_1.object)({
|
|
|
109
109
|
id: AccountWalletPayloadIdStruct,
|
|
110
110
|
type: (0, superstruct_1.literal)(exports.AccountWalletPayloadType.Mnemonic),
|
|
111
111
|
value: (0, superstruct_1.exactOptional)((0, superstruct_1.sensitive)(utils_js_1.BytesStruct)),
|
|
112
|
-
metadata:
|
|
112
|
+
metadata: AccountWalletPayloadMetadataStruct,
|
|
113
113
|
groups: AccountWalletMnemonicGroupsStruct,
|
|
114
114
|
});
|
|
115
115
|
const AccountWalletPrivateKeyPayloadStruct = (0, superstruct_1.object)({
|
|
116
116
|
id: AccountWalletPayloadIdStruct,
|
|
117
117
|
type: (0, superstruct_1.literal)(exports.AccountWalletPayloadType.PrivateKey),
|
|
118
|
-
metadata:
|
|
118
|
+
metadata: AccountWalletPayloadMetadataStruct,
|
|
119
119
|
groups: (0, superstruct_1.array)(AccountWalletPrivateKeyGroupEntryStruct),
|
|
120
120
|
});
|
|
121
121
|
const AccountTreeWalletEntryStruct = (0, superstruct_1.union)([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.cjs","sourceRoot":"","sources":["../../src/state/payload.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyringAccountTypeStruct } from '@metamask/keyring-api';\nimport type { KeyringAccount } from '@metamask/keyring-api';\nimport {\n array,\n assert,\n boolean,\n define,\n enums,\n integer,\n literal,\n object,\n exactOptional,\n refine,\n sensitive,\n string,\n StructError,\n union,\n} from '@metamask/superstruct';\nimport type { Infer } from '@metamask/superstruct';\n\nimport type { DeepReadonly, EncodedBytes } from './utils.js';\nimport { BytesStruct, formatValidationErrorMessages } from './utils.js';\n\n/** Stable cross-device wallet identifier. Format: `wallet:<entropySourceId>`. */\nexport type AccountWalletPayloadId = `wallet:${string}`;\n\n/** Stable cross-device group identifier. Format: `wallet:<entropySourceId>/<groupSubId>`. */\nexport type AccountGroupPayloadId = `${AccountWalletPayloadId}/${string}`;\n\n/**\n * Parsed representation of an {@link AccountGroupPayloadId}.\n */\nexport type ParsedPayloadGroupId = {\n /** The wallet portion of the group ID. */\n walletId: AccountWalletPayloadId;\n /** The group-specific sub-ID (e.g. group index for mnemonic wallets, address for private-key wallets). */\n subId: string;\n};\n\nconst PAYLOAD_GROUP_ID_REGEX = /^(?<walletId>wallet:[^/]+)\\/(?<subId>.+)$/u;\n\n/**\n * Parses a payload group ID into its wallet ID and group sub-ID components.\n *\n * @param groupId - The payload group ID to parse.\n * @returns The parsed wallet ID and group sub-ID.\n * @throws If the group ID format is invalid.\n */\nexport function parsePayloadGroupId(\n groupId: AccountGroupPayloadId,\n): ParsedPayloadGroupId {\n const match = PAYLOAD_GROUP_ID_REGEX.exec(groupId);\n if (!match?.groups) {\n throw new Error(`Invalid payload group ID: \"${groupId}\"`);\n }\n return {\n walletId: match.groups.walletId as AccountWalletPayloadId,\n subId: match.groups.subId,\n };\n}\n\n/**\n * Wallet type discriminants used in serialized {@link AccountTreePayload} entries.\n *\n * Use these constants instead of raw string literals so callers get autocomplete\n * and a single source of truth for the discriminant values.\n */\nexport const AccountWalletPayloadType = {\n Mnemonic: 'mnemonic',\n PrivateKey: 'private-key',\n} as const;\n\nexport type AccountWalletPayloadType =\n (typeof AccountWalletPayloadType)[keyof typeof AccountWalletPayloadType];\n\n/** Wallet-level metadata carried in every payload wallet entry. */\nexport type AccountWalletPayloadMetadata = { name: string };\n\n/** Group-level metadata carried in every payload group entry. */\nexport type AccountWalletGroupPayloadMetadata = {\n name: string;\n pinned: boolean;\n hidden: boolean;\n};\n\n/** A single group entry inside an {@link AccountWalletMnemonicPayload}. */\nexport type AccountWalletMnemonicGroupEntry = {\n /** Stable group payload ID. Format: `<walletPayloadId>/<groupIndex>`. */\n id: AccountGroupPayloadId;\n /** BIP-44 account index this group was derived at. */\n groupIndex: number;\n metadata?: AccountWalletGroupPayloadMetadata;\n};\n\n/**\n * Encoding formats for exported private key material.\n */\nexport const AccountWalletPrivateKeyEncoding = {\n Hexadecimal: 'hexadecimal',\n Base58: 'base58',\n Base32: 'base32',\n} as const;\n\nexport type AccountWalletPrivateKeyEncoding =\n (typeof AccountWalletPrivateKeyEncoding)[keyof typeof AccountWalletPrivateKeyEncoding];\n\n/** A single group entry inside an {@link AccountWalletPrivateKeyPayload}. */\nexport type AccountWalletPrivateKeyGroupEntry = {\n /** Stable group payload ID. Format: `wallet:private-key/<address>`. */\n id: AccountGroupPayloadId;\n /**\n * Private key material. Shape matches `ExportedAccount` from `@metamask/keyring-api/v2`\n * so the importer knows how to decode the key without additional out-of-band information.\n * Absent in metadata-only exports.\n */\n value?: {\n privateKey: EncodedBytes;\n encoding: AccountWalletPrivateKeyEncoding;\n /**\n * Account type from `KeyringAccountType` (e.g. `'eip155:eoa'`, `'bip122:p2wpkh'`).\n * Absent for EVM accounts -- import via `SimpleKeyring`.\n * Present for non-EVM accounts -- routing to the BIP-44 Snap handling this type is not yet implemented.\n */\n type?: KeyringAccount['type'];\n };\n metadata?: AccountWalletGroupPayloadMetadata;\n};\n\n/** Payload entry for an HD (entropy) wallet and its derived account groups. */\nexport type AccountWalletMnemonicPayload = {\n id: AccountWalletPayloadId;\n type: typeof AccountWalletPayloadType.Mnemonic;\n /** BIP-39 mnemonic phrase encoded as bytes. Absent in metadata-only exports. */\n value?: EncodedBytes;\n metadata?: AccountWalletPayloadMetadata;\n groups: AccountWalletMnemonicGroupEntry[];\n};\n\n/**\n * Payload entry for all imported private-key accounts.\n *\n * All local simple-keyring wallets are merged into this single entry;\n * each account is represented as a separate group entry keyed by address.\n */\nexport type AccountWalletPrivateKeyPayload = {\n id: AccountWalletPayloadId;\n type: typeof AccountWalletPayloadType.PrivateKey;\n metadata?: AccountWalletPayloadMetadata;\n groups: AccountWalletPrivateKeyGroupEntry[];\n};\n\n/** Union of all wallet entry types that can appear in an {@link AccountTreePayload}. */\nexport type AccountTreeWalletEntry =\n | AccountWalletMnemonicPayload\n | AccountWalletPrivateKeyPayload;\n\n/** Portable snapshot of the full account tree state (flat versioned format). */\nexport type AccountTreePayload = {\n version: number;\n wallets: AccountTreeWalletEntry[];\n};\n\n/**\n * Deeply read-only wallet view passed to {@link AccountTreeSnapshot.filterWallets}\n * and {@link AccountTreeSnapshot.filterAllGroups} predicates.\n *\n * Entries are deep-cloned and deep-frozen when a snapshot is constructed, so\n * callers cannot mutate wallet IDs, types, secrets, metadata, or groups.\n */\nexport type AccountTreeSnapshotWallet = DeepReadonly<\n AccountWalletMnemonicPayload | AccountWalletPrivateKeyPayload\n>;\n\n/**\n * Deeply read-only group view passed to {@link AccountTreeSnapshot.filterGroups}\n * and {@link AccountTreeSnapshot.filterAllGroups} predicates.\n *\n * Entries are deep-cloned and deep-frozen when a snapshot is constructed, so\n * callers cannot mutate group IDs, secrets, metadata, or parent wallet references.\n */\nexport type AccountTreeSnapshotGroup = DeepReadonly<\n AccountWalletMnemonicGroupEntry | AccountWalletPrivateKeyGroupEntry\n>;\n\n/**\n * Constructs an {@link AccountWalletPayloadId} from an entropy source ID.\n *\n * @param entropySourceId - Stable entropy source ID returned by `HdKeyring.toEntropySourceId()`.\n * @returns The portable wallet payload ID.\n */\nexport function toWalletPayloadId(\n entropySourceId: string,\n): AccountWalletPayloadId {\n return `wallet:${entropySourceId}`;\n}\n\n/**\n * Constructs an {@link AccountGroupPayloadId} from a wallet payload ID and a sub-ID.\n *\n * @param walletId - The wallet payload ID this group belongs to.\n * @param subId - The group-specific sub-ID (e.g. group index for mnemonic wallets, address for private-key wallets).\n * @returns The portable group payload ID.\n */\nexport function toGroupPayloadId(\n walletId: AccountWalletPayloadId,\n subId: string | number,\n): AccountGroupPayloadId {\n return `${walletId}/${subId}`;\n}\n\n/** Options accepted by {@link AccountTreeController.exportState}. */\nexport type ExportStateOptions =\n | {\n /** When `true`, secrets (mnemonic / private keys) are included in the snapshot. */\n includeSecrets: true;\n /** Password verified against the vault before any secret is read. */\n password: string;\n }\n | {\n /** When `false` or omitted, only metadata is exported — no password needed. */\n includeSecrets?: false;\n password?: never;\n };\n\nconst AccountWalletPayloadIdStruct = define<AccountWalletPayloadId>(\n 'AccountWalletPayloadId',\n (value) =>\n typeof value === 'string' && value.startsWith('wallet:')\n ? true\n : 'Expected a wallet payload ID starting with \"wallet:\"',\n);\n\nconst AccountGroupPayloadIdStruct = define<AccountGroupPayloadId>(\n 'AccountGroupPayloadId',\n (value) =>\n typeof value === 'string' && PAYLOAD_GROUP_ID_REGEX.test(value)\n ? true\n : 'Expected a group payload ID in the form \"wallet:<id>/<subId>\"',\n);\n\nconst AccountWalletPayloadMetadataStruct = object({\n name: string(),\n});\n\nconst AccountWalletGroupPayloadMetadataStruct = object({\n name: string(),\n pinned: boolean(),\n hidden: boolean(),\n});\n\nconst AccountWalletPrivateKeyValueStruct = object({\n privateKey: sensitive(BytesStruct),\n encoding: enums(Object.values(AccountWalletPrivateKeyEncoding)),\n type: exactOptional(KeyringAccountTypeStruct),\n});\n\nconst AccountWalletMnemonicGroupEntryStruct = object({\n id: AccountGroupPayloadIdStruct,\n groupIndex: integer(),\n metadata: exactOptional(AccountWalletGroupPayloadMetadataStruct),\n});\n\nconst AccountWalletPrivateKeyGroupEntryStruct = object({\n id: AccountGroupPayloadIdStruct,\n value: exactOptional(AccountWalletPrivateKeyValueStruct),\n metadata: exactOptional(AccountWalletGroupPayloadMetadataStruct),\n});\n\n// The `groups` array in a mnemonic wallet payload must have contiguous group indices starting at 0.\nconst AccountWalletMnemonicGroupsStruct = refine(\n array(AccountWalletMnemonicGroupEntryStruct),\n 'contiguous-group-indices',\n (groups) => {\n let prev: AccountWalletMnemonicGroupEntry | undefined;\n for (const curr of groups) {\n if (prev === undefined && curr.groupIndex !== 0) {\n return `group indices must start at 0; got ${curr.groupIndex}`;\n }\n if (prev !== undefined && curr.groupIndex !== prev.groupIndex + 1) {\n return `group indices must be contiguous and sorted; found gap between index ${prev.groupIndex} and ${curr.groupIndex}`;\n }\n prev = curr;\n }\n return true;\n },\n);\n\nconst AccountWalletMnemonicPayloadStruct = object({\n id: AccountWalletPayloadIdStruct,\n type: literal(AccountWalletPayloadType.Mnemonic),\n value: exactOptional(sensitive(BytesStruct)),\n metadata: exactOptional(AccountWalletPayloadMetadataStruct),\n groups: AccountWalletMnemonicGroupsStruct,\n});\n\nconst AccountWalletPrivateKeyPayloadStruct = object({\n id: AccountWalletPayloadIdStruct,\n type: literal(AccountWalletPayloadType.PrivateKey),\n metadata: exactOptional(AccountWalletPayloadMetadataStruct),\n groups: array(AccountWalletPrivateKeyGroupEntryStruct),\n});\n\nconst AccountTreeWalletEntryStruct = union([\n AccountWalletMnemonicPayloadStruct,\n AccountWalletPrivateKeyPayloadStruct,\n]);\n\n/** Current version of the {@link AccountTreePayload} format. */\nexport const ACCOUNT_TREE_PAYLOAD_CURRENT_VERSION = 1;\n\n/**\n * Superstruct schema for a fully versioned {@link AccountTreePayload}.\n *\n * Pins `version` to exactly {@link ACCOUNT_TREE_PAYLOAD_CURRENT_VERSION} so\n * payloads from newer clients (v2+) are rejected rather than silently\n * mis-handled as v1. Once a migration framework is wired up in\n * {@link AccountTreeSnapshot.deserialize}, older versions will be up-migrated\n * before this struct is checked, and newer versions will require a new struct.\n *\n * Secret fields (`value`, `privateKey`) use the Superstruct `sensitive()`\n * wrapper so validation failures redact secrets from error output.\n */\nexport const AccountTreePayloadStruct = object({\n version: literal(ACCOUNT_TREE_PAYLOAD_CURRENT_VERSION),\n wallets: array(AccountTreeWalletEntryStruct),\n});\n\n/** Inferred TypeScript type for a value matching {@link AccountTreePayloadStruct}. */\nexport type AccountTreePayloadStructType = Infer<\n typeof AccountTreePayloadStruct\n>;\n\n/**\n * Asserts that `value` conforms to the v1 {@link AccountTreePayload} schema.\n *\n * Prefer {@link AccountTreeSnapshot.deserialize} at transport boundaries so\n * validation stays paired with snapshot construction. Use this helper when you\n * already hold a parsed object and need to assert its shape before further\n * processing.\n *\n * @param value - Value to validate.\n * @throws If `value` is not a valid v1 payload, including unsupported wallet types.\n */\nexport function assertAccountTreePayload(\n value: unknown,\n): asserts value is AccountTreePayload {\n try {\n // AccountTreePayloadStruct pins version to ACCOUNT_TREE_PAYLOAD_CURRENT_VERSION,\n // so unknown future versions are rejected here rather than silently mis-handled.\n assert(value, AccountTreePayloadStruct);\n } catch (error) {\n if (error instanceof StructError) {\n throw new Error(\n `Invalid AccountTreePayload: ${formatValidationErrorMessages(error)}`,\n );\n }\n /* istanbul ignore next */\n throw error;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"payload.cjs","sourceRoot":"","sources":["../../src/state/payload.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyringAccountTypeStruct } from '@metamask/keyring-api';\nimport type { KeyringAccount } from '@metamask/keyring-api';\nimport {\n array,\n assert,\n boolean,\n define,\n enums,\n integer,\n literal,\n object,\n exactOptional,\n refine,\n sensitive,\n string,\n StructError,\n union,\n} from '@metamask/superstruct';\nimport type { Infer } from '@metamask/superstruct';\n\nimport type { DeepReadonly, EncodedBytes } from './utils.js';\nimport { BytesStruct, formatValidationErrorMessages } from './utils.js';\n\n/** Stable cross-device wallet identifier. Format: `wallet:<entropySourceId>`. */\nexport type AccountWalletPayloadId = `wallet:${string}`;\n\n/** Stable cross-device group identifier. Format: `wallet:<entropySourceId>/<groupSubId>`. */\nexport type AccountGroupPayloadId = `${AccountWalletPayloadId}/${string}`;\n\n/**\n * Parsed representation of an {@link AccountGroupPayloadId}.\n */\nexport type ParsedPayloadGroupId = {\n /** The wallet portion of the group ID. */\n walletId: AccountWalletPayloadId;\n /** The group-specific sub-ID (e.g. group index for mnemonic wallets, address for private-key wallets). */\n subId: string;\n};\n\nconst PAYLOAD_GROUP_ID_REGEX = /^(?<walletId>wallet:[^/]+)\\/(?<subId>.+)$/u;\n\n/**\n * Parses a payload group ID into its wallet ID and group sub-ID components.\n *\n * @param groupId - The payload group ID to parse.\n * @returns The parsed wallet ID and group sub-ID.\n * @throws If the group ID format is invalid.\n */\nexport function parsePayloadGroupId(\n groupId: AccountGroupPayloadId,\n): ParsedPayloadGroupId {\n const match = PAYLOAD_GROUP_ID_REGEX.exec(groupId);\n if (!match?.groups) {\n throw new Error(`Invalid payload group ID: \"${groupId}\"`);\n }\n return {\n walletId: match.groups.walletId as AccountWalletPayloadId,\n subId: match.groups.subId,\n };\n}\n\n/**\n * Wallet type discriminants used in serialized {@link AccountTreePayload} entries.\n *\n * Use these constants instead of raw string literals so callers get autocomplete\n * and a single source of truth for the discriminant values.\n */\nexport const AccountWalletPayloadType = {\n Mnemonic: 'mnemonic',\n PrivateKey: 'private-key',\n} as const;\n\nexport type AccountWalletPayloadType =\n (typeof AccountWalletPayloadType)[keyof typeof AccountWalletPayloadType];\n\n/** Wallet-level metadata carried in every payload wallet entry. */\nexport type AccountWalletPayloadMetadata = { name: string };\n\n/** Group-level metadata carried in every payload group entry. */\nexport type AccountWalletGroupPayloadMetadata = {\n name: string;\n pinned: boolean;\n hidden: boolean;\n};\n\n/** A single group entry inside an {@link AccountWalletMnemonicPayload}. */\nexport type AccountWalletMnemonicGroupEntry = {\n /** Stable group payload ID. Format: `<walletPayloadId>/<groupIndex>`. */\n id: AccountGroupPayloadId;\n /** BIP-44 account index this group was derived at. */\n groupIndex: number;\n metadata: AccountWalletGroupPayloadMetadata;\n};\n\n/**\n * Encoding formats for exported private key material.\n */\nexport const AccountWalletPrivateKeyEncoding = {\n Hexadecimal: 'hexadecimal',\n Base58: 'base58',\n Base32: 'base32',\n} as const;\n\nexport type AccountWalletPrivateKeyEncoding =\n (typeof AccountWalletPrivateKeyEncoding)[keyof typeof AccountWalletPrivateKeyEncoding];\n\n/** A single group entry inside an {@link AccountWalletPrivateKeyPayload}. */\nexport type AccountWalletPrivateKeyGroupEntry = {\n /** Stable group payload ID. Format: `wallet:private-key/<address>`. */\n id: AccountGroupPayloadId;\n /**\n * Private key material. Shape matches `ExportedAccount` from `@metamask/keyring-api/v2`\n * so the importer knows how to decode the key without additional out-of-band information.\n * Absent in metadata-only exports.\n */\n value?: {\n privateKey: EncodedBytes;\n encoding: AccountWalletPrivateKeyEncoding;\n /**\n * Account type from `KeyringAccountType` (e.g. `'eip155:eoa'`, `'bip122:p2wpkh'`).\n * Absent for EVM accounts -- import via `SimpleKeyring`.\n * Present for non-EVM accounts -- routing to the BIP-44 Snap handling this type is not yet implemented.\n */\n type?: KeyringAccount['type'];\n };\n metadata: AccountWalletGroupPayloadMetadata;\n};\n\n/** Payload entry for an HD (entropy) wallet and its derived account groups. */\nexport type AccountWalletMnemonicPayload = {\n id: AccountWalletPayloadId;\n type: typeof AccountWalletPayloadType.Mnemonic;\n /** BIP-39 mnemonic phrase encoded as bytes. Absent in metadata-only exports. */\n value?: EncodedBytes;\n metadata: AccountWalletPayloadMetadata;\n groups: AccountWalletMnemonicGroupEntry[];\n};\n\n/**\n * Payload entry for all imported private-key accounts.\n *\n * All local simple-keyring wallets are merged into this single entry;\n * each account is represented as a separate group entry keyed by address.\n */\nexport type AccountWalletPrivateKeyPayload = {\n id: AccountWalletPayloadId;\n type: typeof AccountWalletPayloadType.PrivateKey;\n metadata: AccountWalletPayloadMetadata;\n groups: AccountWalletPrivateKeyGroupEntry[];\n};\n\n/** Union of all wallet entry types that can appear in an {@link AccountTreePayload}. */\nexport type AccountTreeWalletEntry =\n | AccountWalletMnemonicPayload\n | AccountWalletPrivateKeyPayload;\n\n/** Portable snapshot of the full account tree state (flat versioned format). */\nexport type AccountTreePayload = {\n version: number;\n wallets: AccountTreeWalletEntry[];\n};\n\n/**\n * Deeply read-only wallet view passed to {@link AccountTreeSnapshot.filterWallets}\n * and {@link AccountTreeSnapshot.filterAllGroups} predicates.\n *\n * Entries are deep-cloned and deep-frozen when a snapshot is constructed, so\n * callers cannot mutate wallet IDs, types, secrets, metadata, or groups.\n */\nexport type AccountTreeSnapshotWallet = DeepReadonly<\n AccountWalletMnemonicPayload | AccountWalletPrivateKeyPayload\n>;\n\n/**\n * Deeply read-only group view passed to {@link AccountTreeSnapshot.filterGroups}\n * and {@link AccountTreeSnapshot.filterAllGroups} predicates.\n *\n * Entries are deep-cloned and deep-frozen when a snapshot is constructed, so\n * callers cannot mutate group IDs, secrets, metadata, or parent wallet references.\n */\nexport type AccountTreeSnapshotGroup = DeepReadonly<\n AccountWalletMnemonicGroupEntry | AccountWalletPrivateKeyGroupEntry\n>;\n\n/**\n * Constructs an {@link AccountWalletPayloadId} from an entropy source ID.\n *\n * @param entropySourceId - Stable entropy source ID returned by `HdKeyring.toEntropySourceId()`.\n * @returns The portable wallet payload ID.\n */\nexport function toWalletPayloadId(\n entropySourceId: string,\n): AccountWalletPayloadId {\n return `wallet:${entropySourceId}`;\n}\n\n/**\n * Constructs an {@link AccountGroupPayloadId} from a wallet payload ID and a sub-ID.\n *\n * @param walletId - The wallet payload ID this group belongs to.\n * @param subId - The group-specific sub-ID (e.g. group index for mnemonic wallets, address for private-key wallets).\n * @returns The portable group payload ID.\n */\nexport function toGroupPayloadId(\n walletId: AccountWalletPayloadId,\n subId: string | number,\n): AccountGroupPayloadId {\n return `${walletId}/${subId}`;\n}\n\n/** Options accepted by {@link AccountTreeController.exportState}. */\nexport type ExportStateOptions =\n | {\n /** When `true`, secrets (mnemonic / private keys) are included in the snapshot. */\n includeSecrets: true;\n /** Password verified against the vault before any secret is read. */\n password: string;\n }\n | {\n /** When `false` or omitted, only metadata is exported — no password needed. */\n includeSecrets?: false;\n password?: never;\n };\n\nconst AccountWalletPayloadIdStruct = define<AccountWalletPayloadId>(\n 'AccountWalletPayloadId',\n (value) =>\n typeof value === 'string' && value.startsWith('wallet:')\n ? true\n : 'Expected a wallet payload ID starting with \"wallet:\"',\n);\n\nconst AccountGroupPayloadIdStruct = define<AccountGroupPayloadId>(\n 'AccountGroupPayloadId',\n (value) =>\n typeof value === 'string' && PAYLOAD_GROUP_ID_REGEX.test(value)\n ? true\n : 'Expected a group payload ID in the form \"wallet:<id>/<subId>\"',\n);\n\nconst AccountWalletPayloadMetadataStruct = object({\n name: string(),\n});\n\nconst AccountWalletGroupPayloadMetadataStruct = object({\n name: string(),\n pinned: boolean(),\n hidden: boolean(),\n});\n\nconst AccountWalletPrivateKeyValueStruct = object({\n privateKey: sensitive(BytesStruct),\n encoding: enums(Object.values(AccountWalletPrivateKeyEncoding)),\n type: exactOptional(KeyringAccountTypeStruct),\n});\n\nconst AccountWalletMnemonicGroupEntryStruct = object({\n id: AccountGroupPayloadIdStruct,\n groupIndex: integer(),\n metadata: AccountWalletGroupPayloadMetadataStruct,\n});\n\nconst AccountWalletPrivateKeyGroupEntryStruct = object({\n id: AccountGroupPayloadIdStruct,\n value: exactOptional(AccountWalletPrivateKeyValueStruct),\n metadata: AccountWalletGroupPayloadMetadataStruct,\n});\n\n// The `groups` array in a mnemonic wallet payload must have contiguous group indices starting at 0.\nconst AccountWalletMnemonicGroupsStruct = refine(\n array(AccountWalletMnemonicGroupEntryStruct),\n 'contiguous-group-indices',\n (groups) => {\n let prev: AccountWalletMnemonicGroupEntry | undefined;\n for (const curr of groups) {\n if (prev === undefined && curr.groupIndex !== 0) {\n return `group indices must start at 0; got ${curr.groupIndex}`;\n }\n if (prev !== undefined && curr.groupIndex !== prev.groupIndex + 1) {\n return `group indices must be contiguous and sorted; found gap between index ${prev.groupIndex} and ${curr.groupIndex}`;\n }\n prev = curr;\n }\n return true;\n },\n);\n\nconst AccountWalletMnemonicPayloadStruct = object({\n id: AccountWalletPayloadIdStruct,\n type: literal(AccountWalletPayloadType.Mnemonic),\n value: exactOptional(sensitive(BytesStruct)),\n metadata: AccountWalletPayloadMetadataStruct,\n groups: AccountWalletMnemonicGroupsStruct,\n});\n\nconst AccountWalletPrivateKeyPayloadStruct = object({\n id: AccountWalletPayloadIdStruct,\n type: literal(AccountWalletPayloadType.PrivateKey),\n metadata: AccountWalletPayloadMetadataStruct,\n groups: array(AccountWalletPrivateKeyGroupEntryStruct),\n});\n\nconst AccountTreeWalletEntryStruct = union([\n AccountWalletMnemonicPayloadStruct,\n AccountWalletPrivateKeyPayloadStruct,\n]);\n\n/** Current version of the {@link AccountTreePayload} format. */\nexport const ACCOUNT_TREE_PAYLOAD_CURRENT_VERSION = 1;\n\n/**\n * Superstruct schema for a fully versioned {@link AccountTreePayload}.\n *\n * Pins `version` to exactly {@link ACCOUNT_TREE_PAYLOAD_CURRENT_VERSION} so\n * payloads from newer clients (v2+) are rejected rather than silently\n * mis-handled as v1. Once a migration framework is wired up in\n * {@link AccountTreeSnapshot.deserialize}, older versions will be up-migrated\n * before this struct is checked, and newer versions will require a new struct.\n *\n * Secret fields (`value`, `privateKey`) use the Superstruct `sensitive()`\n * wrapper so validation failures redact secrets from error output.\n */\nexport const AccountTreePayloadStruct = object({\n version: literal(ACCOUNT_TREE_PAYLOAD_CURRENT_VERSION),\n wallets: array(AccountTreeWalletEntryStruct),\n});\n\n/** Inferred TypeScript type for a value matching {@link AccountTreePayloadStruct}. */\nexport type AccountTreePayloadStructType = Infer<\n typeof AccountTreePayloadStruct\n>;\n\n/**\n * Asserts that `value` conforms to the v1 {@link AccountTreePayload} schema.\n *\n * Prefer {@link AccountTreeSnapshot.deserialize} at transport boundaries so\n * validation stays paired with snapshot construction. Use this helper when you\n * already hold a parsed object and need to assert its shape before further\n * processing.\n *\n * @param value - Value to validate.\n * @throws If `value` is not a valid v1 payload, including unsupported wallet types.\n */\nexport function assertAccountTreePayload(\n value: unknown,\n): asserts value is AccountTreePayload {\n try {\n // AccountTreePayloadStruct pins version to ACCOUNT_TREE_PAYLOAD_CURRENT_VERSION,\n // so unknown future versions are rejected here rather than silently mis-handled.\n assert(value, AccountTreePayloadStruct);\n } catch (error) {\n if (error instanceof StructError) {\n throw new Error(\n `Invalid AccountTreePayload: ${formatValidationErrorMessages(error)}`,\n );\n }\n /* istanbul ignore next */\n throw error;\n }\n}\n"]}
|
package/dist/state/payload.d.cts
CHANGED
|
@@ -49,7 +49,7 @@ export type AccountWalletMnemonicGroupEntry = {
|
|
|
49
49
|
id: AccountGroupPayloadId;
|
|
50
50
|
/** BIP-44 account index this group was derived at. */
|
|
51
51
|
groupIndex: number;
|
|
52
|
-
metadata
|
|
52
|
+
metadata: AccountWalletGroupPayloadMetadata;
|
|
53
53
|
};
|
|
54
54
|
/**
|
|
55
55
|
* Encoding formats for exported private key material.
|
|
@@ -79,7 +79,7 @@ export type AccountWalletPrivateKeyGroupEntry = {
|
|
|
79
79
|
*/
|
|
80
80
|
type?: KeyringAccount['type'];
|
|
81
81
|
};
|
|
82
|
-
metadata
|
|
82
|
+
metadata: AccountWalletGroupPayloadMetadata;
|
|
83
83
|
};
|
|
84
84
|
/** Payload entry for an HD (entropy) wallet and its derived account groups. */
|
|
85
85
|
export type AccountWalletMnemonicPayload = {
|
|
@@ -87,7 +87,7 @@ export type AccountWalletMnemonicPayload = {
|
|
|
87
87
|
type: typeof AccountWalletPayloadType.Mnemonic;
|
|
88
88
|
/** BIP-39 mnemonic phrase encoded as bytes. Absent in metadata-only exports. */
|
|
89
89
|
value?: EncodedBytes;
|
|
90
|
-
metadata
|
|
90
|
+
metadata: AccountWalletPayloadMetadata;
|
|
91
91
|
groups: AccountWalletMnemonicGroupEntry[];
|
|
92
92
|
};
|
|
93
93
|
/**
|
|
@@ -99,7 +99,7 @@ export type AccountWalletMnemonicPayload = {
|
|
|
99
99
|
export type AccountWalletPrivateKeyPayload = {
|
|
100
100
|
id: AccountWalletPayloadId;
|
|
101
101
|
type: typeof AccountWalletPayloadType.PrivateKey;
|
|
102
|
-
metadata
|
|
102
|
+
metadata: AccountWalletPayloadMetadata;
|
|
103
103
|
groups: AccountWalletPrivateKeyGroupEntry[];
|
|
104
104
|
};
|
|
105
105
|
/** Union of all wallet entry types that can appear in an {@link AccountTreePayload}. */
|
|
@@ -169,38 +169,38 @@ export declare const AccountTreePayloadStruct: import("@metamask/superstruct").S
|
|
|
169
169
|
wallets: ({
|
|
170
170
|
id: `wallet:${string}`;
|
|
171
171
|
type: "mnemonic";
|
|
172
|
+
metadata: {
|
|
173
|
+
name: string;
|
|
174
|
+
};
|
|
172
175
|
groups: {
|
|
173
176
|
id: `wallet:${string}/${string}`;
|
|
174
|
-
|
|
175
|
-
metadata?: {
|
|
177
|
+
metadata: {
|
|
176
178
|
name: string;
|
|
177
179
|
pinned: boolean;
|
|
178
180
|
hidden: boolean;
|
|
179
|
-
}
|
|
181
|
+
};
|
|
182
|
+
groupIndex: number;
|
|
180
183
|
}[];
|
|
181
|
-
metadata?: {
|
|
182
|
-
name: string;
|
|
183
|
-
} | undefined;
|
|
184
184
|
value?: EncodedBytes | undefined;
|
|
185
185
|
} | {
|
|
186
186
|
id: `wallet:${string}`;
|
|
187
187
|
type: "private-key";
|
|
188
|
+
metadata: {
|
|
189
|
+
name: string;
|
|
190
|
+
};
|
|
188
191
|
groups: {
|
|
189
192
|
id: `wallet:${string}/${string}`;
|
|
190
|
-
metadata
|
|
193
|
+
metadata: {
|
|
191
194
|
name: string;
|
|
192
195
|
pinned: boolean;
|
|
193
196
|
hidden: boolean;
|
|
194
|
-
}
|
|
197
|
+
};
|
|
195
198
|
value?: {
|
|
196
199
|
privateKey: EncodedBytes;
|
|
197
200
|
encoding: "hexadecimal" | "base58" | "base32";
|
|
198
201
|
type?: "eip155:eoa" | "eip155:erc4337" | "bip122:p2pkh" | "bip122:p2sh" | "bip122:p2wpkh" | "bip122:p2tr" | "solana:data-account" | "tron:eoa" | "stellar:account" | "any:account" | undefined;
|
|
199
202
|
} | undefined;
|
|
200
203
|
}[];
|
|
201
|
-
metadata?: {
|
|
202
|
-
name: string;
|
|
203
|
-
} | undefined;
|
|
204
204
|
})[];
|
|
205
205
|
version: 1;
|
|
206
206
|
}, {
|
|
@@ -208,73 +208,73 @@ export declare const AccountTreePayloadStruct: import("@metamask/superstruct").S
|
|
|
208
208
|
wallets: import("@metamask/superstruct").Struct<({
|
|
209
209
|
id: `wallet:${string}`;
|
|
210
210
|
type: "mnemonic";
|
|
211
|
+
metadata: {
|
|
212
|
+
name: string;
|
|
213
|
+
};
|
|
211
214
|
groups: {
|
|
212
215
|
id: `wallet:${string}/${string}`;
|
|
213
|
-
|
|
214
|
-
metadata?: {
|
|
216
|
+
metadata: {
|
|
215
217
|
name: string;
|
|
216
218
|
pinned: boolean;
|
|
217
219
|
hidden: boolean;
|
|
218
|
-
}
|
|
220
|
+
};
|
|
221
|
+
groupIndex: number;
|
|
219
222
|
}[];
|
|
220
|
-
metadata?: {
|
|
221
|
-
name: string;
|
|
222
|
-
} | undefined;
|
|
223
223
|
value?: EncodedBytes | undefined;
|
|
224
224
|
} | {
|
|
225
225
|
id: `wallet:${string}`;
|
|
226
226
|
type: "private-key";
|
|
227
|
+
metadata: {
|
|
228
|
+
name: string;
|
|
229
|
+
};
|
|
227
230
|
groups: {
|
|
228
231
|
id: `wallet:${string}/${string}`;
|
|
229
|
-
metadata
|
|
232
|
+
metadata: {
|
|
230
233
|
name: string;
|
|
231
234
|
pinned: boolean;
|
|
232
235
|
hidden: boolean;
|
|
233
|
-
}
|
|
236
|
+
};
|
|
234
237
|
value?: {
|
|
235
238
|
privateKey: EncodedBytes;
|
|
236
239
|
encoding: "hexadecimal" | "base58" | "base32";
|
|
237
240
|
type?: "eip155:eoa" | "eip155:erc4337" | "bip122:p2pkh" | "bip122:p2sh" | "bip122:p2wpkh" | "bip122:p2tr" | "solana:data-account" | "tron:eoa" | "stellar:account" | "any:account" | undefined;
|
|
238
241
|
} | undefined;
|
|
239
242
|
}[];
|
|
240
|
-
metadata?: {
|
|
241
|
-
name: string;
|
|
242
|
-
} | undefined;
|
|
243
243
|
})[], import("@metamask/superstruct").Struct<{
|
|
244
244
|
id: `wallet:${string}`;
|
|
245
245
|
type: "mnemonic";
|
|
246
|
+
metadata: {
|
|
247
|
+
name: string;
|
|
248
|
+
};
|
|
246
249
|
groups: {
|
|
247
250
|
id: `wallet:${string}/${string}`;
|
|
248
|
-
|
|
249
|
-
metadata?: {
|
|
251
|
+
metadata: {
|
|
250
252
|
name: string;
|
|
251
253
|
pinned: boolean;
|
|
252
254
|
hidden: boolean;
|
|
253
|
-
}
|
|
255
|
+
};
|
|
256
|
+
groupIndex: number;
|
|
254
257
|
}[];
|
|
255
|
-
metadata?: {
|
|
256
|
-
name: string;
|
|
257
|
-
} | undefined;
|
|
258
258
|
value?: EncodedBytes | undefined;
|
|
259
259
|
} | {
|
|
260
260
|
id: `wallet:${string}`;
|
|
261
261
|
type: "private-key";
|
|
262
|
+
metadata: {
|
|
263
|
+
name: string;
|
|
264
|
+
};
|
|
262
265
|
groups: {
|
|
263
266
|
id: `wallet:${string}/${string}`;
|
|
264
|
-
metadata
|
|
267
|
+
metadata: {
|
|
265
268
|
name: string;
|
|
266
269
|
pinned: boolean;
|
|
267
270
|
hidden: boolean;
|
|
268
|
-
}
|
|
271
|
+
};
|
|
269
272
|
value?: {
|
|
270
273
|
privateKey: EncodedBytes;
|
|
271
274
|
encoding: "hexadecimal" | "base58" | "base32";
|
|
272
275
|
type?: "eip155:eoa" | "eip155:erc4337" | "bip122:p2pkh" | "bip122:p2sh" | "bip122:p2wpkh" | "bip122:p2tr" | "solana:data-account" | "tron:eoa" | "stellar:account" | "any:account" | undefined;
|
|
273
276
|
} | undefined;
|
|
274
277
|
}[];
|
|
275
|
-
metadata?: {
|
|
276
|
-
name: string;
|
|
277
|
-
} | undefined;
|
|
278
278
|
}, null>>;
|
|
279
279
|
}>;
|
|
280
280
|
/** Inferred TypeScript type for a value matching {@link AccountTreePayloadStruct}. */
|