@metamask-previews/seedless-onboarding-controller 0.0.0-preview-8a04e037 → 0.0.0-preview-c4b7ea2e

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.
Files changed (56) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/dist/SecretMetadata.cjs +185 -0
  3. package/dist/SecretMetadata.cjs.map +1 -0
  4. package/dist/SecretMetadata.d.cts +101 -0
  5. package/dist/SecretMetadata.d.cts.map +1 -0
  6. package/dist/SecretMetadata.d.mts +101 -0
  7. package/dist/SecretMetadata.d.mts.map +1 -0
  8. package/dist/SecretMetadata.mjs +181 -0
  9. package/dist/SecretMetadata.mjs.map +1 -0
  10. package/dist/SeedlessOnboardingController.cjs +190 -57
  11. package/dist/SeedlessOnboardingController.cjs.map +1 -1
  12. package/dist/SeedlessOnboardingController.d.cts +46 -8
  13. package/dist/SeedlessOnboardingController.d.cts.map +1 -1
  14. package/dist/SeedlessOnboardingController.d.mts +46 -8
  15. package/dist/SeedlessOnboardingController.d.mts.map +1 -1
  16. package/dist/SeedlessOnboardingController.mjs +191 -58
  17. package/dist/SeedlessOnboardingController.mjs.map +1 -1
  18. package/dist/constants.cjs +35 -21
  19. package/dist/constants.cjs.map +1 -1
  20. package/dist/constants.d.cts +15 -2
  21. package/dist/constants.d.cts.map +1 -1
  22. package/dist/constants.d.mts +15 -2
  23. package/dist/constants.d.mts.map +1 -1
  24. package/dist/constants.mjs +34 -20
  25. package/dist/constants.mjs.map +1 -1
  26. package/dist/errors.cjs +29 -29
  27. package/dist/errors.cjs.map +1 -1
  28. package/dist/errors.d.cts +1 -10
  29. package/dist/errors.d.cts.map +1 -1
  30. package/dist/errors.d.mts +1 -10
  31. package/dist/errors.d.mts.map +1 -1
  32. package/dist/errors.mjs +30 -30
  33. package/dist/errors.mjs.map +1 -1
  34. package/dist/index.cjs +4 -17
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +2 -2
  37. package/dist/index.d.cts.map +1 -1
  38. package/dist/index.d.mts +2 -2
  39. package/dist/index.d.mts.map +1 -1
  40. package/dist/index.mjs +2 -2
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/types.cjs.map +1 -1
  43. package/dist/types.d.cts +33 -23
  44. package/dist/types.d.cts.map +1 -1
  45. package/dist/types.d.mts +33 -23
  46. package/dist/types.d.mts.map +1 -1
  47. package/dist/types.mjs.map +1 -1
  48. package/package.json +6 -2
  49. package/dist/SeedPhraseMetadata.cjs +0 -146
  50. package/dist/SeedPhraseMetadata.cjs.map +0 -1
  51. package/dist/SeedPhraseMetadata.d.cts +0 -82
  52. package/dist/SeedPhraseMetadata.d.cts.map +0 -1
  53. package/dist/SeedPhraseMetadata.d.mts +0 -82
  54. package/dist/SeedPhraseMetadata.d.mts.map +0 -1
  55. package/dist/SeedPhraseMetadata.mjs +0 -142
  56. package/dist/SeedPhraseMetadata.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -9,12 +9,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Added
11
11
 
12
- - Initial implementation of the seedless onboarding controller. ([#5671](https://github.com/MetaMask/core/pull/5671))
12
+ - Initial implementation of the seedless onboarding controller. ([#5874](https://github.com/MetaMask/core/pull/5874))
13
13
  - Authenticate OAuth user using the seedless onboarding flow and determine if the user is already registered or not
14
14
  - Create a new Toprf key and backup seed phrase
15
15
  - Add a new seed phrase backup to the metadata store
16
16
  - Add array of new seed phrase backups to the metadata store in batch (useful in multi-srp flow)
17
17
  - Fetch seed phrase metadata from the metadata store
18
18
  - Update the password of the seedless onboarding flow
19
+ - Support multi SRP sync using social login. ([#5875](https://github.com/MetaMask/core/pull/5875))
20
+ - Update Metadata to support multiple types of secrets (SRP, PrivateKey).
21
+ - Add `Controller Lock` which will sync with `Keyring Lock`.
22
+ - Updated `VaultEncryptor` type in constructor args and is compulsory to provided relevant encryptor to constructor.
23
+ - Added new non-persisted states, `encryptionKey` and `encryptionSalt` to decrypt the vault when password is not available.
24
+ - Update `password` param in `fetchAllSeedPhrases` method to optional. If password is not provided, `cached EncryptionKey` will be used.
19
25
 
20
26
  [Unreleased]: https://github.com/MetaMask/core/
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _SecretMetadata_data, _SecretMetadata_timestamp, _SecretMetadata_type, _SecretMetadata_version;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.SecretMetadata = void 0;
16
+ const utils_1 = require("@metamask/utils");
17
+ const constants_1 = require("./constants.cjs");
18
+ /**
19
+ * SecretMetadata is a class that adds metadata to the secret.
20
+ *
21
+ * It contains the secret and the timestamp when it was created.
22
+ * It is used to store the secret in the metadata store.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const secretMetadata = new SecretMetadata(secret);
27
+ * ```
28
+ */
29
+ class SecretMetadata {
30
+ /**
31
+ * Create a new SecretMetadata instance.
32
+ *
33
+ * @param data - The secret to add metadata to.
34
+ * @param options - The options for the secret metadata.
35
+ * @param options.timestamp - The timestamp when the secret was created.
36
+ * @param options.type - The type of the secret.
37
+ */
38
+ constructor(data, options) {
39
+ _SecretMetadata_data.set(this, void 0);
40
+ _SecretMetadata_timestamp.set(this, void 0);
41
+ _SecretMetadata_type.set(this, void 0);
42
+ _SecretMetadata_version.set(this, void 0);
43
+ __classPrivateFieldSet(this, _SecretMetadata_data, data, "f");
44
+ __classPrivateFieldSet(this, _SecretMetadata_timestamp, options?.timestamp ?? Date.now(), "f");
45
+ __classPrivateFieldSet(this, _SecretMetadata_type, options?.type ?? constants_1.SecretType.Mnemonic, "f");
46
+ __classPrivateFieldSet(this, _SecretMetadata_version, options?.version ?? constants_1.SecretMetadataVersion.V1, "f");
47
+ }
48
+ /**
49
+ * Create an Array of SecretMetadata instances from an array of secrets.
50
+ *
51
+ * To respect the order of the secrets, we add the index to the timestamp
52
+ * so that the first secret backup will have the oldest timestamp
53
+ * and the last secret backup will have the newest timestamp.
54
+ *
55
+ * @param data - The data to add metadata to.
56
+ * @param data.value - The SeedPhrase/PrivateKey to add metadata to.
57
+ * @param data.options - The options for the seed phrase metadata.
58
+ * @returns The SecretMetadata instances.
59
+ */
60
+ static fromBatch(data) {
61
+ const timestamp = Date.now();
62
+ return data.map((d, index) => {
63
+ // To respect the order of the seed phrases, we add the index to the timestamp
64
+ // so that the first seed phrase backup will have the oldest timestamp
65
+ // and the last seed phrase backup will have the newest timestamp
66
+ const backupCreatedAt = d.options?.timestamp ?? timestamp + index * 5;
67
+ return new SecretMetadata(d.value, {
68
+ timestamp: backupCreatedAt,
69
+ type: d.options?.type,
70
+ });
71
+ });
72
+ }
73
+ /**
74
+ * Assert that the provided value is a valid seed phrase metadata.
75
+ *
76
+ * @param value - The value to check.
77
+ * @throws If the value is not a valid seed phrase metadata.
78
+ */
79
+ static assertIsValidSecretMetadataJson(value) {
80
+ if (typeof value !== 'object' ||
81
+ !value ||
82
+ !('data' in value) ||
83
+ typeof value.data !== 'string' ||
84
+ !('timestamp' in value) ||
85
+ typeof value.timestamp !== 'number') {
86
+ throw new Error(constants_1.SeedlessOnboardingControllerErrorMessage.InvalidSecretMetadata);
87
+ }
88
+ }
89
+ /**
90
+ * Parse the SecretMetadata from the metadata store and return the array of SecretMetadata instances.
91
+ *
92
+ * This method also sorts the secrets by timestamp in ascending order, i.e. the oldest secret will be the first element in the array.
93
+ *
94
+ * @param secretMetadataArr - The array of SecretMetadata from the metadata store.
95
+ * @param filterType - The type of the secret to filter.
96
+ * @returns The array of SecretMetadata instances.
97
+ */
98
+ static parseSecretsFromMetadataStore(secretMetadataArr, filterType) {
99
+ const parsedSecertMetadata = secretMetadataArr.map((metadata) => SecretMetadata.fromRawMetadata(metadata));
100
+ const secrets = SecretMetadata.sort(parsedSecertMetadata);
101
+ if (filterType) {
102
+ return secrets.filter((secret) => secret.type === filterType);
103
+ }
104
+ return secrets;
105
+ }
106
+ /**
107
+ * Parse and create the SecretMetadata instance from the raw metadata bytes.
108
+ *
109
+ * @param rawMetadata - The raw metadata.
110
+ * @returns The parsed secret metadata.
111
+ */
112
+ static fromRawMetadata(rawMetadata) {
113
+ const serializedMetadata = (0, utils_1.bytesToString)(rawMetadata);
114
+ const parsedMetadata = JSON.parse(serializedMetadata);
115
+ SecretMetadata.assertIsValidSecretMetadataJson(parsedMetadata);
116
+ // if the type is not provided, we default to Mnemonic for the backwards compatibility
117
+ const type = parsedMetadata.type ?? constants_1.SecretType.Mnemonic;
118
+ const version = parsedMetadata.version ?? constants_1.SecretMetadataVersion.V1;
119
+ let data;
120
+ try {
121
+ data = (0, utils_1.base64ToBytes)(parsedMetadata.data);
122
+ }
123
+ catch {
124
+ data = parsedMetadata.data;
125
+ }
126
+ return new SecretMetadata(data, {
127
+ timestamp: parsedMetadata.timestamp,
128
+ type,
129
+ version,
130
+ });
131
+ }
132
+ /**
133
+ * Sort the seed phrases by timestamp.
134
+ *
135
+ * @param data - The secret metadata array to sort.
136
+ * @param order - The order to sort the seed phrases. Default is `desc`.
137
+ *
138
+ * @returns The sorted secret metadata array.
139
+ */
140
+ static sort(data, order = 'asc') {
141
+ return data.sort((a, b) => {
142
+ if (order === 'asc') {
143
+ return a.timestamp - b.timestamp;
144
+ }
145
+ return b.timestamp - a.timestamp;
146
+ });
147
+ }
148
+ get data() {
149
+ return __classPrivateFieldGet(this, _SecretMetadata_data, "f");
150
+ }
151
+ get timestamp() {
152
+ return __classPrivateFieldGet(this, _SecretMetadata_timestamp, "f");
153
+ }
154
+ get type() {
155
+ return __classPrivateFieldGet(this, _SecretMetadata_type, "f");
156
+ }
157
+ get version() {
158
+ return __classPrivateFieldGet(this, _SecretMetadata_version, "f");
159
+ }
160
+ /**
161
+ * Serialize the secret metadata and convert it to a Uint8Array.
162
+ *
163
+ * @returns The serialized SecretMetadata value in bytes.
164
+ */
165
+ toBytes() {
166
+ let _data = __classPrivateFieldGet(this, _SecretMetadata_data, "f");
167
+ if (__classPrivateFieldGet(this, _SecretMetadata_data, "f") instanceof Uint8Array) {
168
+ // encode the raw secret to base64 encoded string
169
+ // to create more compacted metadata
170
+ _data = (0, utils_1.bytesToBase64)(__classPrivateFieldGet(this, _SecretMetadata_data, "f"));
171
+ }
172
+ // serialize the metadata to a JSON string
173
+ const serializedMetadata = JSON.stringify({
174
+ data: _data,
175
+ timestamp: __classPrivateFieldGet(this, _SecretMetadata_timestamp, "f"),
176
+ type: __classPrivateFieldGet(this, _SecretMetadata_type, "f"),
177
+ version: __classPrivateFieldGet(this, _SecretMetadata_version, "f"),
178
+ });
179
+ // convert the serialized metadata to bytes(Uint8Array)
180
+ return (0, utils_1.stringToBytes)(serializedMetadata);
181
+ }
182
+ }
183
+ exports.SecretMetadata = SecretMetadata;
184
+ _SecretMetadata_data = new WeakMap(), _SecretMetadata_timestamp = new WeakMap(), _SecretMetadata_type = new WeakMap(), _SecretMetadata_version = new WeakMap();
185
+ //# sourceMappingURL=SecretMetadata.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecretMetadata.cjs","sourceRoot":"","sources":["../src/SecretMetadata.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n base64ToBytes,\n bytesToBase64,\n stringToBytes,\n bytesToString,\n} from '@metamask/utils';\n\nimport {\n SeedlessOnboardingControllerErrorMessage,\n SecretType,\n SecretMetadataVersion,\n} from './constants';\nimport type { SecretDataType, SecretMetadataOptions } from './types';\n\ntype ISecretMetadata<DataType extends SecretDataType = Uint8Array> = {\n data: DataType;\n timestamp: number;\n type: SecretType;\n version: SecretMetadataVersion;\n toBytes: () => Uint8Array;\n};\n\n/**\n * This is like `SecretMetadata`, but without the `data` and `toBytes`\n * methods in which the data is `base64` encoded for more compacted\n * metadata.\n */\ntype SecretMetadataJson<DataType extends SecretDataType> = Omit<\n ISecretMetadata<DataType>,\n 'data' | 'toBytes'\n> & {\n data: string; // base64 encoded string\n};\n\n/**\n * SecretMetadata is a class that adds metadata to the secret.\n *\n * It contains the secret and the timestamp when it was created.\n * It is used to store the secret in the metadata store.\n *\n * @example\n * ```ts\n * const secretMetadata = new SecretMetadata(secret);\n * ```\n */\nexport class SecretMetadata<DataType extends SecretDataType = Uint8Array>\n implements ISecretMetadata<DataType>\n{\n readonly #data: DataType;\n\n readonly #timestamp: number;\n\n readonly #type: SecretType;\n\n readonly #version: SecretMetadataVersion;\n\n /**\n * Create a new SecretMetadata instance.\n *\n * @param data - The secret to add metadata to.\n * @param options - The options for the secret metadata.\n * @param options.timestamp - The timestamp when the secret was created.\n * @param options.type - The type of the secret.\n */\n constructor(data: DataType, options?: Partial<SecretMetadataOptions>) {\n this.#data = data;\n this.#timestamp = options?.timestamp ?? Date.now();\n this.#type = options?.type ?? SecretType.Mnemonic;\n this.#version = options?.version ?? SecretMetadataVersion.V1;\n }\n\n /**\n * Create an Array of SecretMetadata instances from an array of secrets.\n *\n * To respect the order of the secrets, we add the index to the timestamp\n * so that the first secret backup will have the oldest timestamp\n * and the last secret backup will have the newest timestamp.\n *\n * @param data - The data to add metadata to.\n * @param data.value - The SeedPhrase/PrivateKey to add metadata to.\n * @param data.options - The options for the seed phrase metadata.\n * @returns The SecretMetadata instances.\n */\n static fromBatch<DataType extends SecretDataType = Uint8Array>(\n data: {\n value: DataType;\n options?: Partial<SecretMetadataOptions>;\n }[],\n ): SecretMetadata<DataType>[] {\n const timestamp = Date.now();\n return data.map((d, index) => {\n // To respect the order of the seed phrases, we add the index to the timestamp\n // so that the first seed phrase backup will have the oldest timestamp\n // and the last seed phrase backup will have the newest timestamp\n const backupCreatedAt = d.options?.timestamp ?? timestamp + index * 5;\n return new SecretMetadata(d.value, {\n timestamp: backupCreatedAt,\n type: d.options?.type,\n });\n });\n }\n\n /**\n * Assert that the provided value is a valid seed phrase metadata.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid seed phrase metadata.\n */\n static assertIsValidSecretMetadataJson<\n DataType extends SecretDataType = Uint8Array,\n >(value: unknown): asserts value is SecretMetadataJson<DataType> {\n if (\n typeof value !== 'object' ||\n !value ||\n !('data' in value) ||\n typeof value.data !== 'string' ||\n !('timestamp' in value) ||\n typeof value.timestamp !== 'number'\n ) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.InvalidSecretMetadata,\n );\n }\n }\n\n /**\n * Parse the SecretMetadata from the metadata store and return the array of SecretMetadata instances.\n *\n * This method also sorts the secrets by timestamp in ascending order, i.e. the oldest secret will be the first element in the array.\n *\n * @param secretMetadataArr - The array of SecretMetadata from the metadata store.\n * @param filterType - The type of the secret to filter.\n * @returns The array of SecretMetadata instances.\n */\n static parseSecretsFromMetadataStore<\n DataType extends SecretDataType = Uint8Array,\n >(\n secretMetadataArr: Uint8Array[],\n filterType?: SecretType,\n ): SecretMetadata<DataType>[] {\n const parsedSecertMetadata = secretMetadataArr.map((metadata) =>\n SecretMetadata.fromRawMetadata<DataType>(metadata),\n );\n\n const secrets = SecretMetadata.sort(parsedSecertMetadata);\n\n if (filterType) {\n return secrets.filter((secret) => secret.type === filterType);\n }\n\n return secrets;\n }\n\n /**\n * Parse and create the SecretMetadata instance from the raw metadata bytes.\n *\n * @param rawMetadata - The raw metadata.\n * @returns The parsed secret metadata.\n */\n static fromRawMetadata<DataType extends SecretDataType>(\n rawMetadata: Uint8Array,\n ): SecretMetadata<DataType> {\n const serializedMetadata = bytesToString(rawMetadata);\n const parsedMetadata = JSON.parse(serializedMetadata);\n\n SecretMetadata.assertIsValidSecretMetadataJson<DataType>(parsedMetadata);\n\n // if the type is not provided, we default to Mnemonic for the backwards compatibility\n const type = parsedMetadata.type ?? SecretType.Mnemonic;\n const version = parsedMetadata.version ?? SecretMetadataVersion.V1;\n\n let data: DataType;\n try {\n data = base64ToBytes(parsedMetadata.data) as DataType;\n } catch {\n data = parsedMetadata.data as DataType;\n }\n\n return new SecretMetadata<DataType>(data, {\n timestamp: parsedMetadata.timestamp,\n type,\n version,\n });\n }\n\n /**\n * Sort the seed phrases by timestamp.\n *\n * @param data - The secret metadata array to sort.\n * @param order - The order to sort the seed phrases. Default is `desc`.\n *\n * @returns The sorted secret metadata array.\n */\n static sort<DataType extends SecretDataType = Uint8Array>(\n data: SecretMetadata<DataType>[],\n order: 'asc' | 'desc' = 'asc',\n ): SecretMetadata<DataType>[] {\n return data.sort((a, b) => {\n if (order === 'asc') {\n return a.timestamp - b.timestamp;\n }\n return b.timestamp - a.timestamp;\n });\n }\n\n get data(): DataType {\n return this.#data;\n }\n\n get timestamp() {\n return this.#timestamp;\n }\n\n get type() {\n return this.#type;\n }\n\n get version() {\n return this.#version;\n }\n\n /**\n * Serialize the secret metadata and convert it to a Uint8Array.\n *\n * @returns The serialized SecretMetadata value in bytes.\n */\n toBytes(): Uint8Array {\n let _data: unknown = this.#data;\n if (this.#data instanceof Uint8Array) {\n // encode the raw secret to base64 encoded string\n // to create more compacted metadata\n _data = bytesToBase64(this.#data);\n }\n\n // serialize the metadata to a JSON string\n const serializedMetadata = JSON.stringify({\n data: _data,\n timestamp: this.#timestamp,\n type: this.#type,\n version: this.#version,\n });\n\n // convert the serialized metadata to bytes(Uint8Array)\n return stringToBytes(serializedMetadata);\n }\n}\n"]}
@@ -0,0 +1,101 @@
1
+ import { SecretType, SecretMetadataVersion } from "./constants.cjs";
2
+ import type { SecretDataType, SecretMetadataOptions } from "./types.cjs";
3
+ type ISecretMetadata<DataType extends SecretDataType = Uint8Array> = {
4
+ data: DataType;
5
+ timestamp: number;
6
+ type: SecretType;
7
+ version: SecretMetadataVersion;
8
+ toBytes: () => Uint8Array;
9
+ };
10
+ /**
11
+ * This is like `SecretMetadata`, but without the `data` and `toBytes`
12
+ * methods in which the data is `base64` encoded for more compacted
13
+ * metadata.
14
+ */
15
+ type SecretMetadataJson<DataType extends SecretDataType> = Omit<ISecretMetadata<DataType>, 'data' | 'toBytes'> & {
16
+ data: string;
17
+ };
18
+ /**
19
+ * SecretMetadata is a class that adds metadata to the secret.
20
+ *
21
+ * It contains the secret and the timestamp when it was created.
22
+ * It is used to store the secret in the metadata store.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const secretMetadata = new SecretMetadata(secret);
27
+ * ```
28
+ */
29
+ export declare class SecretMetadata<DataType extends SecretDataType = Uint8Array> implements ISecretMetadata<DataType> {
30
+ #private;
31
+ /**
32
+ * Create a new SecretMetadata instance.
33
+ *
34
+ * @param data - The secret to add metadata to.
35
+ * @param options - The options for the secret metadata.
36
+ * @param options.timestamp - The timestamp when the secret was created.
37
+ * @param options.type - The type of the secret.
38
+ */
39
+ constructor(data: DataType, options?: Partial<SecretMetadataOptions>);
40
+ /**
41
+ * Create an Array of SecretMetadata instances from an array of secrets.
42
+ *
43
+ * To respect the order of the secrets, we add the index to the timestamp
44
+ * so that the first secret backup will have the oldest timestamp
45
+ * and the last secret backup will have the newest timestamp.
46
+ *
47
+ * @param data - The data to add metadata to.
48
+ * @param data.value - The SeedPhrase/PrivateKey to add metadata to.
49
+ * @param data.options - The options for the seed phrase metadata.
50
+ * @returns The SecretMetadata instances.
51
+ */
52
+ static fromBatch<DataType extends SecretDataType = Uint8Array>(data: {
53
+ value: DataType;
54
+ options?: Partial<SecretMetadataOptions>;
55
+ }[]): SecretMetadata<DataType>[];
56
+ /**
57
+ * Assert that the provided value is a valid seed phrase metadata.
58
+ *
59
+ * @param value - The value to check.
60
+ * @throws If the value is not a valid seed phrase metadata.
61
+ */
62
+ static assertIsValidSecretMetadataJson<DataType extends SecretDataType = Uint8Array>(value: unknown): asserts value is SecretMetadataJson<DataType>;
63
+ /**
64
+ * Parse the SecretMetadata from the metadata store and return the array of SecretMetadata instances.
65
+ *
66
+ * This method also sorts the secrets by timestamp in ascending order, i.e. the oldest secret will be the first element in the array.
67
+ *
68
+ * @param secretMetadataArr - The array of SecretMetadata from the metadata store.
69
+ * @param filterType - The type of the secret to filter.
70
+ * @returns The array of SecretMetadata instances.
71
+ */
72
+ static parseSecretsFromMetadataStore<DataType extends SecretDataType = Uint8Array>(secretMetadataArr: Uint8Array[], filterType?: SecretType): SecretMetadata<DataType>[];
73
+ /**
74
+ * Parse and create the SecretMetadata instance from the raw metadata bytes.
75
+ *
76
+ * @param rawMetadata - The raw metadata.
77
+ * @returns The parsed secret metadata.
78
+ */
79
+ static fromRawMetadata<DataType extends SecretDataType>(rawMetadata: Uint8Array): SecretMetadata<DataType>;
80
+ /**
81
+ * Sort the seed phrases by timestamp.
82
+ *
83
+ * @param data - The secret metadata array to sort.
84
+ * @param order - The order to sort the seed phrases. Default is `desc`.
85
+ *
86
+ * @returns The sorted secret metadata array.
87
+ */
88
+ static sort<DataType extends SecretDataType = Uint8Array>(data: SecretMetadata<DataType>[], order?: 'asc' | 'desc'): SecretMetadata<DataType>[];
89
+ get data(): DataType;
90
+ get timestamp(): number;
91
+ get type(): SecretType;
92
+ get version(): SecretMetadataVersion;
93
+ /**
94
+ * Serialize the secret metadata and convert it to a Uint8Array.
95
+ *
96
+ * @returns The serialized SecretMetadata value in bytes.
97
+ */
98
+ toBytes(): Uint8Array;
99
+ }
100
+ export {};
101
+ //# sourceMappingURL=SecretMetadata.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecretMetadata.d.cts","sourceRoot":"","sources":["../src/SecretMetadata.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,UAAU,EACV,qBAAqB,EACtB,wBAAoB;AACrB,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,oBAAgB;AAErE,KAAK,eAAe,CAAC,QAAQ,SAAS,cAAc,GAAG,UAAU,IAAI;IACnE,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,OAAO,EAAE,MAAM,UAAU,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,KAAK,kBAAkB,CAAC,QAAQ,SAAS,cAAc,IAAI,IAAI,CAC7D,eAAe,CAAC,QAAQ,CAAC,EACzB,MAAM,GAAG,SAAS,CACnB,GAAG;IACF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;;;;;;GAUG;AACH,qBAAa,cAAc,CAAC,QAAQ,SAAS,cAAc,GAAG,UAAU,CACtE,YAAW,eAAe,CAAC,QAAQ,CAAC;;IAUpC;;;;;;;OAOG;gBACS,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAOpE;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,SAAS,CAAC,QAAQ,SAAS,cAAc,GAAG,UAAU,EAC3D,IAAI,EAAE;QACJ,KAAK,EAAE,QAAQ,CAAC;QAChB,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;KAC1C,EAAE,GACF,cAAc,CAAC,QAAQ,CAAC,EAAE;IAc7B;;;;;OAKG;IACH,MAAM,CAAC,+BAA+B,CACpC,QAAQ,SAAS,cAAc,GAAG,UAAU,EAC5C,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,kBAAkB,CAAC,QAAQ,CAAC;IAehE;;;;;;;;OAQG;IACH,MAAM,CAAC,6BAA6B,CAClC,QAAQ,SAAS,cAAc,GAAG,UAAU,EAE5C,iBAAiB,EAAE,UAAU,EAAE,EAC/B,UAAU,CAAC,EAAE,UAAU,GACtB,cAAc,CAAC,QAAQ,CAAC,EAAE;IAc7B;;;;;OAKG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,SAAS,cAAc,EACpD,WAAW,EAAE,UAAU,GACtB,cAAc,CAAC,QAAQ,CAAC;IAwB3B;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CAAC,QAAQ,SAAS,cAAc,GAAG,UAAU,EACtD,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,EAChC,KAAK,GAAE,KAAK,GAAG,MAAc,GAC5B,cAAc,CAAC,QAAQ,CAAC,EAAE;IAS7B,IAAI,IAAI,IAAI,QAAQ,CAEnB;IAED,IAAI,SAAS,WAEZ;IAED,IAAI,IAAI,eAEP;IAED,IAAI,OAAO,0BAEV;IAED;;;;OAIG;IACH,OAAO,IAAI,UAAU;CAmBtB"}
@@ -0,0 +1,101 @@
1
+ import { SecretType, SecretMetadataVersion } from "./constants.mjs";
2
+ import type { SecretDataType, SecretMetadataOptions } from "./types.mjs";
3
+ type ISecretMetadata<DataType extends SecretDataType = Uint8Array> = {
4
+ data: DataType;
5
+ timestamp: number;
6
+ type: SecretType;
7
+ version: SecretMetadataVersion;
8
+ toBytes: () => Uint8Array;
9
+ };
10
+ /**
11
+ * This is like `SecretMetadata`, but without the `data` and `toBytes`
12
+ * methods in which the data is `base64` encoded for more compacted
13
+ * metadata.
14
+ */
15
+ type SecretMetadataJson<DataType extends SecretDataType> = Omit<ISecretMetadata<DataType>, 'data' | 'toBytes'> & {
16
+ data: string;
17
+ };
18
+ /**
19
+ * SecretMetadata is a class that adds metadata to the secret.
20
+ *
21
+ * It contains the secret and the timestamp when it was created.
22
+ * It is used to store the secret in the metadata store.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const secretMetadata = new SecretMetadata(secret);
27
+ * ```
28
+ */
29
+ export declare class SecretMetadata<DataType extends SecretDataType = Uint8Array> implements ISecretMetadata<DataType> {
30
+ #private;
31
+ /**
32
+ * Create a new SecretMetadata instance.
33
+ *
34
+ * @param data - The secret to add metadata to.
35
+ * @param options - The options for the secret metadata.
36
+ * @param options.timestamp - The timestamp when the secret was created.
37
+ * @param options.type - The type of the secret.
38
+ */
39
+ constructor(data: DataType, options?: Partial<SecretMetadataOptions>);
40
+ /**
41
+ * Create an Array of SecretMetadata instances from an array of secrets.
42
+ *
43
+ * To respect the order of the secrets, we add the index to the timestamp
44
+ * so that the first secret backup will have the oldest timestamp
45
+ * and the last secret backup will have the newest timestamp.
46
+ *
47
+ * @param data - The data to add metadata to.
48
+ * @param data.value - The SeedPhrase/PrivateKey to add metadata to.
49
+ * @param data.options - The options for the seed phrase metadata.
50
+ * @returns The SecretMetadata instances.
51
+ */
52
+ static fromBatch<DataType extends SecretDataType = Uint8Array>(data: {
53
+ value: DataType;
54
+ options?: Partial<SecretMetadataOptions>;
55
+ }[]): SecretMetadata<DataType>[];
56
+ /**
57
+ * Assert that the provided value is a valid seed phrase metadata.
58
+ *
59
+ * @param value - The value to check.
60
+ * @throws If the value is not a valid seed phrase metadata.
61
+ */
62
+ static assertIsValidSecretMetadataJson<DataType extends SecretDataType = Uint8Array>(value: unknown): asserts value is SecretMetadataJson<DataType>;
63
+ /**
64
+ * Parse the SecretMetadata from the metadata store and return the array of SecretMetadata instances.
65
+ *
66
+ * This method also sorts the secrets by timestamp in ascending order, i.e. the oldest secret will be the first element in the array.
67
+ *
68
+ * @param secretMetadataArr - The array of SecretMetadata from the metadata store.
69
+ * @param filterType - The type of the secret to filter.
70
+ * @returns The array of SecretMetadata instances.
71
+ */
72
+ static parseSecretsFromMetadataStore<DataType extends SecretDataType = Uint8Array>(secretMetadataArr: Uint8Array[], filterType?: SecretType): SecretMetadata<DataType>[];
73
+ /**
74
+ * Parse and create the SecretMetadata instance from the raw metadata bytes.
75
+ *
76
+ * @param rawMetadata - The raw metadata.
77
+ * @returns The parsed secret metadata.
78
+ */
79
+ static fromRawMetadata<DataType extends SecretDataType>(rawMetadata: Uint8Array): SecretMetadata<DataType>;
80
+ /**
81
+ * Sort the seed phrases by timestamp.
82
+ *
83
+ * @param data - The secret metadata array to sort.
84
+ * @param order - The order to sort the seed phrases. Default is `desc`.
85
+ *
86
+ * @returns The sorted secret metadata array.
87
+ */
88
+ static sort<DataType extends SecretDataType = Uint8Array>(data: SecretMetadata<DataType>[], order?: 'asc' | 'desc'): SecretMetadata<DataType>[];
89
+ get data(): DataType;
90
+ get timestamp(): number;
91
+ get type(): SecretType;
92
+ get version(): SecretMetadataVersion;
93
+ /**
94
+ * Serialize the secret metadata and convert it to a Uint8Array.
95
+ *
96
+ * @returns The serialized SecretMetadata value in bytes.
97
+ */
98
+ toBytes(): Uint8Array;
99
+ }
100
+ export {};
101
+ //# sourceMappingURL=SecretMetadata.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecretMetadata.d.mts","sourceRoot":"","sources":["../src/SecretMetadata.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,UAAU,EACV,qBAAqB,EACtB,wBAAoB;AACrB,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,oBAAgB;AAErE,KAAK,eAAe,CAAC,QAAQ,SAAS,cAAc,GAAG,UAAU,IAAI;IACnE,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,OAAO,EAAE,MAAM,UAAU,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,KAAK,kBAAkB,CAAC,QAAQ,SAAS,cAAc,IAAI,IAAI,CAC7D,eAAe,CAAC,QAAQ,CAAC,EACzB,MAAM,GAAG,SAAS,CACnB,GAAG;IACF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;;;;;;GAUG;AACH,qBAAa,cAAc,CAAC,QAAQ,SAAS,cAAc,GAAG,UAAU,CACtE,YAAW,eAAe,CAAC,QAAQ,CAAC;;IAUpC;;;;;;;OAOG;gBACS,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAOpE;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,SAAS,CAAC,QAAQ,SAAS,cAAc,GAAG,UAAU,EAC3D,IAAI,EAAE;QACJ,KAAK,EAAE,QAAQ,CAAC;QAChB,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;KAC1C,EAAE,GACF,cAAc,CAAC,QAAQ,CAAC,EAAE;IAc7B;;;;;OAKG;IACH,MAAM,CAAC,+BAA+B,CACpC,QAAQ,SAAS,cAAc,GAAG,UAAU,EAC5C,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,kBAAkB,CAAC,QAAQ,CAAC;IAehE;;;;;;;;OAQG;IACH,MAAM,CAAC,6BAA6B,CAClC,QAAQ,SAAS,cAAc,GAAG,UAAU,EAE5C,iBAAiB,EAAE,UAAU,EAAE,EAC/B,UAAU,CAAC,EAAE,UAAU,GACtB,cAAc,CAAC,QAAQ,CAAC,EAAE;IAc7B;;;;;OAKG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,SAAS,cAAc,EACpD,WAAW,EAAE,UAAU,GACtB,cAAc,CAAC,QAAQ,CAAC;IAwB3B;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CAAC,QAAQ,SAAS,cAAc,GAAG,UAAU,EACtD,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,EAChC,KAAK,GAAE,KAAK,GAAG,MAAc,GAC5B,cAAc,CAAC,QAAQ,CAAC,EAAE;IAS7B,IAAI,IAAI,IAAI,QAAQ,CAEnB;IAED,IAAI,SAAS,WAEZ;IAED,IAAI,IAAI,eAEP;IAED,IAAI,OAAO,0BAEV;IAED;;;;OAIG;IACH,OAAO,IAAI,UAAU;CAmBtB"}
@@ -0,0 +1,181 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _SecretMetadata_data, _SecretMetadata_timestamp, _SecretMetadata_type, _SecretMetadata_version;
13
+ import { base64ToBytes, bytesToBase64, stringToBytes, bytesToString } from "@metamask/utils";
14
+ import { SeedlessOnboardingControllerErrorMessage, SecretType, SecretMetadataVersion } from "./constants.mjs";
15
+ /**
16
+ * SecretMetadata is a class that adds metadata to the secret.
17
+ *
18
+ * It contains the secret and the timestamp when it was created.
19
+ * It is used to store the secret in the metadata store.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const secretMetadata = new SecretMetadata(secret);
24
+ * ```
25
+ */
26
+ export class SecretMetadata {
27
+ /**
28
+ * Create a new SecretMetadata instance.
29
+ *
30
+ * @param data - The secret to add metadata to.
31
+ * @param options - The options for the secret metadata.
32
+ * @param options.timestamp - The timestamp when the secret was created.
33
+ * @param options.type - The type of the secret.
34
+ */
35
+ constructor(data, options) {
36
+ _SecretMetadata_data.set(this, void 0);
37
+ _SecretMetadata_timestamp.set(this, void 0);
38
+ _SecretMetadata_type.set(this, void 0);
39
+ _SecretMetadata_version.set(this, void 0);
40
+ __classPrivateFieldSet(this, _SecretMetadata_data, data, "f");
41
+ __classPrivateFieldSet(this, _SecretMetadata_timestamp, options?.timestamp ?? Date.now(), "f");
42
+ __classPrivateFieldSet(this, _SecretMetadata_type, options?.type ?? SecretType.Mnemonic, "f");
43
+ __classPrivateFieldSet(this, _SecretMetadata_version, options?.version ?? SecretMetadataVersion.V1, "f");
44
+ }
45
+ /**
46
+ * Create an Array of SecretMetadata instances from an array of secrets.
47
+ *
48
+ * To respect the order of the secrets, we add the index to the timestamp
49
+ * so that the first secret backup will have the oldest timestamp
50
+ * and the last secret backup will have the newest timestamp.
51
+ *
52
+ * @param data - The data to add metadata to.
53
+ * @param data.value - The SeedPhrase/PrivateKey to add metadata to.
54
+ * @param data.options - The options for the seed phrase metadata.
55
+ * @returns The SecretMetadata instances.
56
+ */
57
+ static fromBatch(data) {
58
+ const timestamp = Date.now();
59
+ return data.map((d, index) => {
60
+ // To respect the order of the seed phrases, we add the index to the timestamp
61
+ // so that the first seed phrase backup will have the oldest timestamp
62
+ // and the last seed phrase backup will have the newest timestamp
63
+ const backupCreatedAt = d.options?.timestamp ?? timestamp + index * 5;
64
+ return new SecretMetadata(d.value, {
65
+ timestamp: backupCreatedAt,
66
+ type: d.options?.type,
67
+ });
68
+ });
69
+ }
70
+ /**
71
+ * Assert that the provided value is a valid seed phrase metadata.
72
+ *
73
+ * @param value - The value to check.
74
+ * @throws If the value is not a valid seed phrase metadata.
75
+ */
76
+ static assertIsValidSecretMetadataJson(value) {
77
+ if (typeof value !== 'object' ||
78
+ !value ||
79
+ !('data' in value) ||
80
+ typeof value.data !== 'string' ||
81
+ !('timestamp' in value) ||
82
+ typeof value.timestamp !== 'number') {
83
+ throw new Error(SeedlessOnboardingControllerErrorMessage.InvalidSecretMetadata);
84
+ }
85
+ }
86
+ /**
87
+ * Parse the SecretMetadata from the metadata store and return the array of SecretMetadata instances.
88
+ *
89
+ * This method also sorts the secrets by timestamp in ascending order, i.e. the oldest secret will be the first element in the array.
90
+ *
91
+ * @param secretMetadataArr - The array of SecretMetadata from the metadata store.
92
+ * @param filterType - The type of the secret to filter.
93
+ * @returns The array of SecretMetadata instances.
94
+ */
95
+ static parseSecretsFromMetadataStore(secretMetadataArr, filterType) {
96
+ const parsedSecertMetadata = secretMetadataArr.map((metadata) => SecretMetadata.fromRawMetadata(metadata));
97
+ const secrets = SecretMetadata.sort(parsedSecertMetadata);
98
+ if (filterType) {
99
+ return secrets.filter((secret) => secret.type === filterType);
100
+ }
101
+ return secrets;
102
+ }
103
+ /**
104
+ * Parse and create the SecretMetadata instance from the raw metadata bytes.
105
+ *
106
+ * @param rawMetadata - The raw metadata.
107
+ * @returns The parsed secret metadata.
108
+ */
109
+ static fromRawMetadata(rawMetadata) {
110
+ const serializedMetadata = bytesToString(rawMetadata);
111
+ const parsedMetadata = JSON.parse(serializedMetadata);
112
+ SecretMetadata.assertIsValidSecretMetadataJson(parsedMetadata);
113
+ // if the type is not provided, we default to Mnemonic for the backwards compatibility
114
+ const type = parsedMetadata.type ?? SecretType.Mnemonic;
115
+ const version = parsedMetadata.version ?? SecretMetadataVersion.V1;
116
+ let data;
117
+ try {
118
+ data = base64ToBytes(parsedMetadata.data);
119
+ }
120
+ catch {
121
+ data = parsedMetadata.data;
122
+ }
123
+ return new SecretMetadata(data, {
124
+ timestamp: parsedMetadata.timestamp,
125
+ type,
126
+ version,
127
+ });
128
+ }
129
+ /**
130
+ * Sort the seed phrases by timestamp.
131
+ *
132
+ * @param data - The secret metadata array to sort.
133
+ * @param order - The order to sort the seed phrases. Default is `desc`.
134
+ *
135
+ * @returns The sorted secret metadata array.
136
+ */
137
+ static sort(data, order = 'asc') {
138
+ return data.sort((a, b) => {
139
+ if (order === 'asc') {
140
+ return a.timestamp - b.timestamp;
141
+ }
142
+ return b.timestamp - a.timestamp;
143
+ });
144
+ }
145
+ get data() {
146
+ return __classPrivateFieldGet(this, _SecretMetadata_data, "f");
147
+ }
148
+ get timestamp() {
149
+ return __classPrivateFieldGet(this, _SecretMetadata_timestamp, "f");
150
+ }
151
+ get type() {
152
+ return __classPrivateFieldGet(this, _SecretMetadata_type, "f");
153
+ }
154
+ get version() {
155
+ return __classPrivateFieldGet(this, _SecretMetadata_version, "f");
156
+ }
157
+ /**
158
+ * Serialize the secret metadata and convert it to a Uint8Array.
159
+ *
160
+ * @returns The serialized SecretMetadata value in bytes.
161
+ */
162
+ toBytes() {
163
+ let _data = __classPrivateFieldGet(this, _SecretMetadata_data, "f");
164
+ if (__classPrivateFieldGet(this, _SecretMetadata_data, "f") instanceof Uint8Array) {
165
+ // encode the raw secret to base64 encoded string
166
+ // to create more compacted metadata
167
+ _data = bytesToBase64(__classPrivateFieldGet(this, _SecretMetadata_data, "f"));
168
+ }
169
+ // serialize the metadata to a JSON string
170
+ const serializedMetadata = JSON.stringify({
171
+ data: _data,
172
+ timestamp: __classPrivateFieldGet(this, _SecretMetadata_timestamp, "f"),
173
+ type: __classPrivateFieldGet(this, _SecretMetadata_type, "f"),
174
+ version: __classPrivateFieldGet(this, _SecretMetadata_version, "f"),
175
+ });
176
+ // convert the serialized metadata to bytes(Uint8Array)
177
+ return stringToBytes(serializedMetadata);
178
+ }
179
+ }
180
+ _SecretMetadata_data = new WeakMap(), _SecretMetadata_timestamp = new WeakMap(), _SecretMetadata_type = new WeakMap(), _SecretMetadata_version = new WeakMap();
181
+ //# sourceMappingURL=SecretMetadata.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecretMetadata.mjs","sourceRoot":"","sources":["../src/SecretMetadata.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n base64ToBytes,\n bytesToBase64,\n stringToBytes,\n bytesToString,\n} from '@metamask/utils';\n\nimport {\n SeedlessOnboardingControllerErrorMessage,\n SecretType,\n SecretMetadataVersion,\n} from './constants';\nimport type { SecretDataType, SecretMetadataOptions } from './types';\n\ntype ISecretMetadata<DataType extends SecretDataType = Uint8Array> = {\n data: DataType;\n timestamp: number;\n type: SecretType;\n version: SecretMetadataVersion;\n toBytes: () => Uint8Array;\n};\n\n/**\n * This is like `SecretMetadata`, but without the `data` and `toBytes`\n * methods in which the data is `base64` encoded for more compacted\n * metadata.\n */\ntype SecretMetadataJson<DataType extends SecretDataType> = Omit<\n ISecretMetadata<DataType>,\n 'data' | 'toBytes'\n> & {\n data: string; // base64 encoded string\n};\n\n/**\n * SecretMetadata is a class that adds metadata to the secret.\n *\n * It contains the secret and the timestamp when it was created.\n * It is used to store the secret in the metadata store.\n *\n * @example\n * ```ts\n * const secretMetadata = new SecretMetadata(secret);\n * ```\n */\nexport class SecretMetadata<DataType extends SecretDataType = Uint8Array>\n implements ISecretMetadata<DataType>\n{\n readonly #data: DataType;\n\n readonly #timestamp: number;\n\n readonly #type: SecretType;\n\n readonly #version: SecretMetadataVersion;\n\n /**\n * Create a new SecretMetadata instance.\n *\n * @param data - The secret to add metadata to.\n * @param options - The options for the secret metadata.\n * @param options.timestamp - The timestamp when the secret was created.\n * @param options.type - The type of the secret.\n */\n constructor(data: DataType, options?: Partial<SecretMetadataOptions>) {\n this.#data = data;\n this.#timestamp = options?.timestamp ?? Date.now();\n this.#type = options?.type ?? SecretType.Mnemonic;\n this.#version = options?.version ?? SecretMetadataVersion.V1;\n }\n\n /**\n * Create an Array of SecretMetadata instances from an array of secrets.\n *\n * To respect the order of the secrets, we add the index to the timestamp\n * so that the first secret backup will have the oldest timestamp\n * and the last secret backup will have the newest timestamp.\n *\n * @param data - The data to add metadata to.\n * @param data.value - The SeedPhrase/PrivateKey to add metadata to.\n * @param data.options - The options for the seed phrase metadata.\n * @returns The SecretMetadata instances.\n */\n static fromBatch<DataType extends SecretDataType = Uint8Array>(\n data: {\n value: DataType;\n options?: Partial<SecretMetadataOptions>;\n }[],\n ): SecretMetadata<DataType>[] {\n const timestamp = Date.now();\n return data.map((d, index) => {\n // To respect the order of the seed phrases, we add the index to the timestamp\n // so that the first seed phrase backup will have the oldest timestamp\n // and the last seed phrase backup will have the newest timestamp\n const backupCreatedAt = d.options?.timestamp ?? timestamp + index * 5;\n return new SecretMetadata(d.value, {\n timestamp: backupCreatedAt,\n type: d.options?.type,\n });\n });\n }\n\n /**\n * Assert that the provided value is a valid seed phrase metadata.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid seed phrase metadata.\n */\n static assertIsValidSecretMetadataJson<\n DataType extends SecretDataType = Uint8Array,\n >(value: unknown): asserts value is SecretMetadataJson<DataType> {\n if (\n typeof value !== 'object' ||\n !value ||\n !('data' in value) ||\n typeof value.data !== 'string' ||\n !('timestamp' in value) ||\n typeof value.timestamp !== 'number'\n ) {\n throw new Error(\n SeedlessOnboardingControllerErrorMessage.InvalidSecretMetadata,\n );\n }\n }\n\n /**\n * Parse the SecretMetadata from the metadata store and return the array of SecretMetadata instances.\n *\n * This method also sorts the secrets by timestamp in ascending order, i.e. the oldest secret will be the first element in the array.\n *\n * @param secretMetadataArr - The array of SecretMetadata from the metadata store.\n * @param filterType - The type of the secret to filter.\n * @returns The array of SecretMetadata instances.\n */\n static parseSecretsFromMetadataStore<\n DataType extends SecretDataType = Uint8Array,\n >(\n secretMetadataArr: Uint8Array[],\n filterType?: SecretType,\n ): SecretMetadata<DataType>[] {\n const parsedSecertMetadata = secretMetadataArr.map((metadata) =>\n SecretMetadata.fromRawMetadata<DataType>(metadata),\n );\n\n const secrets = SecretMetadata.sort(parsedSecertMetadata);\n\n if (filterType) {\n return secrets.filter((secret) => secret.type === filterType);\n }\n\n return secrets;\n }\n\n /**\n * Parse and create the SecretMetadata instance from the raw metadata bytes.\n *\n * @param rawMetadata - The raw metadata.\n * @returns The parsed secret metadata.\n */\n static fromRawMetadata<DataType extends SecretDataType>(\n rawMetadata: Uint8Array,\n ): SecretMetadata<DataType> {\n const serializedMetadata = bytesToString(rawMetadata);\n const parsedMetadata = JSON.parse(serializedMetadata);\n\n SecretMetadata.assertIsValidSecretMetadataJson<DataType>(parsedMetadata);\n\n // if the type is not provided, we default to Mnemonic for the backwards compatibility\n const type = parsedMetadata.type ?? SecretType.Mnemonic;\n const version = parsedMetadata.version ?? SecretMetadataVersion.V1;\n\n let data: DataType;\n try {\n data = base64ToBytes(parsedMetadata.data) as DataType;\n } catch {\n data = parsedMetadata.data as DataType;\n }\n\n return new SecretMetadata<DataType>(data, {\n timestamp: parsedMetadata.timestamp,\n type,\n version,\n });\n }\n\n /**\n * Sort the seed phrases by timestamp.\n *\n * @param data - The secret metadata array to sort.\n * @param order - The order to sort the seed phrases. Default is `desc`.\n *\n * @returns The sorted secret metadata array.\n */\n static sort<DataType extends SecretDataType = Uint8Array>(\n data: SecretMetadata<DataType>[],\n order: 'asc' | 'desc' = 'asc',\n ): SecretMetadata<DataType>[] {\n return data.sort((a, b) => {\n if (order === 'asc') {\n return a.timestamp - b.timestamp;\n }\n return b.timestamp - a.timestamp;\n });\n }\n\n get data(): DataType {\n return this.#data;\n }\n\n get timestamp() {\n return this.#timestamp;\n }\n\n get type() {\n return this.#type;\n }\n\n get version() {\n return this.#version;\n }\n\n /**\n * Serialize the secret metadata and convert it to a Uint8Array.\n *\n * @returns The serialized SecretMetadata value in bytes.\n */\n toBytes(): Uint8Array {\n let _data: unknown = this.#data;\n if (this.#data instanceof Uint8Array) {\n // encode the raw secret to base64 encoded string\n // to create more compacted metadata\n _data = bytesToBase64(this.#data);\n }\n\n // serialize the metadata to a JSON string\n const serializedMetadata = JSON.stringify({\n data: _data,\n timestamp: this.#timestamp,\n type: this.#type,\n version: this.#version,\n });\n\n // convert the serialized metadata to bytes(Uint8Array)\n return stringToBytes(serializedMetadata);\n }\n}\n"]}