@idos-network/enclave 1.1.0

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -0
  3. package/dist/base-0xSNl4rW.d.mts +140 -0
  4. package/dist/base-0xSNl4rW.d.mts.map +1 -0
  5. package/dist/client-BSkUuHYm.mjs +1196 -0
  6. package/dist/client-BSkUuHYm.mjs.map +1 -0
  7. package/dist/client-Bu0aO5sT.d.mts +38 -0
  8. package/dist/client-Bu0aO5sT.d.mts.map +1 -0
  9. package/dist/index.d.mts +16 -0
  10. package/dist/index.d.mts.map +1 -0
  11. package/dist/index.mjs +2 -0
  12. package/dist/keys-RuC1M-_K.mjs +187 -0
  13. package/dist/keys-RuC1M-_K.mjs.map +1 -0
  14. package/dist/local.d.mts +96 -0
  15. package/dist/local.d.mts.map +1 -0
  16. package/dist/local.mjs +253 -0
  17. package/dist/local.mjs.map +1 -0
  18. package/dist/mpc/index.d.mts +3 -0
  19. package/dist/mpc/index.mjs +2 -0
  20. package/dist/types-DKsOwtWL.d.mts +73 -0
  21. package/dist/types-DKsOwtWL.d.mts.map +1 -0
  22. package/package.json +76 -0
  23. package/src/base.test.ts +137 -0
  24. package/src/base.ts +306 -0
  25. package/src/index.ts +3 -0
  26. package/src/keys.ts +10 -0
  27. package/src/local.test.ts +113 -0
  28. package/src/local.ts +495 -0
  29. package/src/mpc/api.ts +122 -0
  30. package/src/mpc/client.ts +411 -0
  31. package/src/mpc/engine-client.ts +144 -0
  32. package/src/mpc/generated/IdosContract.ts +92 -0
  33. package/src/mpc/index.ts +2 -0
  34. package/src/mpc/secretsharing/f256.ts +122 -0
  35. package/src/mpc/secretsharing/finite-field-element.ts +50 -0
  36. package/src/mpc/secretsharing/lagrange.ts +163 -0
  37. package/src/mpc/secretsharing/polynomial.ts +84 -0
  38. package/src/mpc/secretsharing/secret-share-factory.ts +30 -0
  39. package/src/mpc/secretsharing/secret-shares.ts +20 -0
  40. package/src/mpc/secretsharing/shamir-secret-shares.ts +164 -0
  41. package/src/mpc/secretsharing/xor-secret-shares.ts +68 -0
  42. package/src/mpc/types.ts +117 -0
  43. package/src/types.ts +37 -0
package/dist/local.mjs ADDED
@@ -0,0 +1,253 @@
1
+ import { n as BaseProvider, t as STORAGE_KEYS } from "./keys-RuC1M-_K.mjs";
2
+ import { t as Client } from "./client-BSkUuHYm.mjs";
3
+ import { base64Codec, base64Encode, hexDecode, hexEncode, utf8Decode, utf8Encode } from "@idos-network/utils/codecs";
4
+ import { generatePassword } from "@idos-network/utils/cryptography";
5
+ import { decrypt, encrypt, keyDerivation } from "@idos-network/utils/encryption";
6
+ import { LocalStorageStore } from "@idos-network/utils/store";
7
+ import { syncScrypt } from "scrypt-js";
8
+ import nacl from "tweetnacl";
9
+ //#region src/local.ts
10
+ var LocalEnclave = class extends BaseProvider {
11
+ allowedEncryptionStores;
12
+ store;
13
+ storeBase64;
14
+ storeObfuscated;
15
+ storeObfuscatedBase64;
16
+ mpcClientInstance;
17
+ storedEncryptionProfile;
18
+ constructor(options) {
19
+ super(options);
20
+ this.allowedEncryptionStores = options.allowedEncryptionStores ?? ["user"];
21
+ this.store = options.store ?? new LocalStorageStore();
22
+ this.storeObfuscated = this.store.pipeCodec(this.userIdObfuscationCodec());
23
+ this.storeBase64 = this.store.pipeCodec(base64Codec);
24
+ this.storeObfuscatedBase64 = this.store.pipeCodec(this.userIdObfuscationCodec()).pipeCodec(base64Codec);
25
+ if (options.mpcConfiguration) this.mpcClientInstance = new Client(options.mpcConfiguration.nodeUrl, options.mpcConfiguration.contractAddress, options.mpcConfiguration.numMalicious, options.mpcConfiguration.numNodes, options.mpcConfiguration.numToReconstruct, options.walletType ?? "EVM", options.walletAddress ?? "", options.walletPublicKey);
26
+ }
27
+ /** @override parent method to reset the enclave */
28
+ async reset() {
29
+ await super.reset();
30
+ this.storedEncryptionProfile = void 0;
31
+ this.store.reset();
32
+ }
33
+ /** @override parent method to reconfigure the enclave */
34
+ async reconfigure(options = {}) {
35
+ await super.reconfigure(options);
36
+ if (this.mpcClientInstance && options.walletType && options.walletAddress) this.mpcClientInstance.reconfigure(options.walletType, options.walletAddress ?? "", options.walletPublicKey);
37
+ }
38
+ /**
39
+ * Return a codec that encrypts/decrypts data using a key derived from the provider's user ID.
40
+ *
41
+ * This ensures that data is minimally obfuscated to avoid low-sophistication attacks.
42
+ */
43
+ userIdObfuscationCodec() {
44
+ const self = this;
45
+ const toKey = (userId, salt) => syncScrypt(utf8Encode(userId), salt, 16384, 8, 1, nacl.secretbox.keyLength);
46
+ return {
47
+ encode(data) {
48
+ if (!self.options.userId) throw new Error("User ID required for encryption");
49
+ const dataBytes = utf8Encode(data);
50
+ const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
51
+ const salt = nacl.randomBytes(16);
52
+ const key = toKey(self.options.userId, salt);
53
+ const payload = nacl.secretbox(dataBytes, nonce, key);
54
+ const combined = new Uint8Array(salt.length + nonce.length + payload.length);
55
+ combined.set(salt, 0);
56
+ combined.set(nonce, salt.length);
57
+ combined.set(payload, salt.length + nonce.length);
58
+ return `0x${hexEncode(combined)}`;
59
+ },
60
+ decode(payload) {
61
+ if (!self.options.userId) throw new Error("User ID required for decryption");
62
+ if (payload.slice(0, 2) !== "0x") throw new Error(`missing 0x prefix: ${payload}`);
63
+ const combined = hexDecode(payload.slice(2));
64
+ const salt = combined.slice(0, 16);
65
+ const nonce = combined.slice(16, 16 + nacl.secretbox.nonceLength);
66
+ const ciphertext = combined.slice(16 + nacl.secretbox.nonceLength);
67
+ const key = toKey(self.options.userId, salt);
68
+ const result = nacl.secretbox.open(ciphertext, nonce, key);
69
+ if (!result) throw new Error("Failed to decrypt data");
70
+ return utf8Decode(result);
71
+ }
72
+ };
73
+ }
74
+ /** @see parent method extended with loading the profile from the store */
75
+ async load() {
76
+ await super.load();
77
+ const userId = await this.store.get(STORAGE_KEYS.USER_ID);
78
+ if (userId) this.options.userId = userId;
79
+ let password = await this.storeObfuscated.get(STORAGE_KEYS.OBFUSCATED_PASSWORD);
80
+ if (!password) {
81
+ password = await this.store.get(STORAGE_KEYS.DEPRECATED___PASSWORD);
82
+ if (!password) return;
83
+ await this.storeObfuscated.set(STORAGE_KEYS.OBFUSCATED_PASSWORD, password);
84
+ }
85
+ await this.store.delete(STORAGE_KEYS.DEPRECATED___PASSWORD);
86
+ let encryptionSecretKey = await this.storeObfuscatedBase64.get(STORAGE_KEYS.OBFUSCATED_BASE64_ENCRYPTION_SECRET_KEY);
87
+ if (!encryptionSecretKey) {
88
+ encryptionSecretKey = await this.storeBase64.get(STORAGE_KEYS.DEPRECATED___ENCRYPTION_SECRET_KEY);
89
+ if (!encryptionSecretKey) return;
90
+ await this.storeObfuscatedBase64.set(STORAGE_KEYS.OBFUSCATED_BASE64_ENCRYPTION_SECRET_KEY, encryptionSecretKey);
91
+ }
92
+ await this.store.delete(STORAGE_KEYS.DEPRECATED___ENCRYPTION_SECRET_KEY);
93
+ await this.store.delete(STORAGE_KEYS.DEPRECATED___ENCRYPTION_PRIVATE_KEY);
94
+ if (!password || !userId || !encryptionSecretKey) return;
95
+ let encryptionPasswordStore = await this.store.get(STORAGE_KEYS.ENCRYPTION_PASSWORD_STORE);
96
+ if (!encryptionPasswordStore || encryptionPasswordStore === "password") {
97
+ encryptionPasswordStore = "user";
98
+ await this.store.set(STORAGE_KEYS.ENCRYPTION_PASSWORD_STORE, encryptionPasswordStore);
99
+ }
100
+ this.storedEncryptionProfile = {
101
+ userId,
102
+ password,
103
+ keyPair: nacl.box.keyPair.fromSecretKey(encryptionSecretKey),
104
+ encryptionPasswordStore
105
+ };
106
+ }
107
+ /**
108
+ * Encrypts a message to a receiver.
109
+ * This method also checks if the user is authorized to use the keys.
110
+ *
111
+ * @param message - The message to encrypt.
112
+ * @param receiverPublicKey - The public key of the receiver.
113
+ *
114
+ * @returns The encrypted message.
115
+ */
116
+ async encrypt(message, receiverPublicKey) {
117
+ const { keyPair } = await this.getPrivateEncryptionProfile();
118
+ return encrypt(message, keyPair.publicKey, receiverPublicKey);
119
+ }
120
+ /**
121
+ * Decrypts a message from a sender.
122
+ * This method also checks if the user is authorized to use the keys.
123
+ *
124
+ * @param message - The message to decrypt.
125
+ * @param senderPublicKey - The public key of the sender.
126
+ *
127
+ * @returns The decrypted message.
128
+ */
129
+ async decrypt(message, senderPublicKey) {
130
+ const { keyPair } = await this.getPrivateEncryptionProfile();
131
+ return decrypt(message, keyPair, senderPublicKey);
132
+ }
133
+ /**
134
+ * @see BaseProvider#getPrivateEncryptionProfile
135
+ */
136
+ async getPrivateEncryptionProfile(skipGuard = false) {
137
+ if (this.storedEncryptionProfile) {
138
+ let canBeUsed = this.storedEncryptionProfile.userId === this.userId;
139
+ if (canBeUsed && !skipGuard) canBeUsed = await this.guardKeys();
140
+ if (canBeUsed) return this.storedEncryptionProfile;
141
+ await this.reset();
142
+ }
143
+ let password;
144
+ let encryptionPasswordStore;
145
+ const context = await this.getPasswordContext();
146
+ if (context.encryptionPasswordStore === "user") {
147
+ await this.store.setRememberDuration(context.duration);
148
+ password = context.password;
149
+ encryptionPasswordStore = context.encryptionPasswordStore;
150
+ }
151
+ if (context.encryptionPasswordStore === "mpc") {
152
+ await this.store.setRememberDuration(void 0);
153
+ password = await this.ensureMPCPassword();
154
+ encryptionPasswordStore = "mpc";
155
+ }
156
+ if (!password || !encryptionPasswordStore) throw new Error("Password or encryption password store is not found");
157
+ return this.createEncryptionProfileFromPassword(password, this.userId, encryptionPasswordStore);
158
+ }
159
+ /** @see BaseProvider#ensureUserEncryptionProfile */
160
+ async ensureUserEncryptionProfile() {
161
+ const { keyPair, encryptionPasswordStore, userId } = await this.getPrivateEncryptionProfile();
162
+ return {
163
+ userId,
164
+ userEncryptionPublicKey: base64Encode(keyPair.publicKey),
165
+ encryptionPasswordStore
166
+ };
167
+ }
168
+ /**
169
+ * This method needs to check `options` and should derive the password context from it.
170
+ *
171
+ * @returns The password context.
172
+ */
173
+ async getPasswordContext() {
174
+ throw new Error("Method 'getPasswordContext' has to be implemented in the subclass.");
175
+ }
176
+ /**
177
+ * Creates and store encryption profile from a password.
178
+ *
179
+ * @param password - The password to use.
180
+ * @param userId - The user id to use.
181
+ * @param encryptionPasswordStore - The encryption password store to use.
182
+ *
183
+ * @returns The encryption profile.
184
+ */
185
+ async createEncryptionProfileFromPassword(password, userId, encryptionPasswordStore) {
186
+ const secretKey = await keyDerivation(password, userId);
187
+ const keyPair = nacl.box.keyPair.fromSecretKey(secretKey);
188
+ await this.store.set(STORAGE_KEYS.USER_ID, userId);
189
+ await this.storeObfuscated.set(STORAGE_KEYS.OBFUSCATED_PASSWORD, password);
190
+ await this.store.delete(STORAGE_KEYS.DEPRECATED___PASSWORD);
191
+ await this.store.set(STORAGE_KEYS.ENCRYPTION_PASSWORD_STORE, encryptionPasswordStore);
192
+ await this.storeObfuscatedBase64.set(STORAGE_KEYS.OBFUSCATED_BASE64_ENCRYPTION_SECRET_KEY, keyPair.secretKey);
193
+ await this.store.delete(STORAGE_KEYS.DEPRECATED___ENCRYPTION_SECRET_KEY);
194
+ await this.storeBase64.set(STORAGE_KEYS.ENCRYPTION_PUBLIC_KEY, keyPair.publicKey);
195
+ this.storedEncryptionProfile = {
196
+ userId,
197
+ password,
198
+ keyPair,
199
+ encryptionPasswordStore
200
+ };
201
+ return this.storedEncryptionProfile;
202
+ }
203
+ async ensureMPCPassword() {
204
+ if (this.options?.mode !== "new") {
205
+ const { status: downloadStatus, secret: downloadedPassword } = await this.downloadSecret();
206
+ if (downloadStatus === "ok" && downloadedPassword) return utf8Decode(downloadedPassword);
207
+ throw Error("A secret might be stored at MPC ZK nodes, but can't be obtained");
208
+ }
209
+ const password = generatePassword();
210
+ const { status: uploadStatus } = await this.uploadSecret(password);
211
+ if (uploadStatus !== "success") throw Error(`A secret upload failed with status: ${uploadStatus}`);
212
+ return password;
213
+ }
214
+ get mpcClient() {
215
+ if (!this.mpcClientInstance) throw new Error("MPC client is not initialized");
216
+ return this.mpcClientInstance;
217
+ }
218
+ async downloadSecret() {
219
+ if (!this.options.walletAddress) throw new Error("walletAddress is not found");
220
+ const ephemeralKeyPair = nacl.box.keyPair();
221
+ const downloadRequest = this.mpcClient.downloadRequest(ephemeralKeyPair.publicKey);
222
+ const messageToSign = this.mpcClient.downloadMessageToSign(downloadRequest);
223
+ const signedMessage = await this.signTypedData(messageToSign.domain, messageToSign.types, messageToSign.value);
224
+ return this.mpcClient.downloadSecret(this.userId, downloadRequest, signedMessage, ephemeralKeyPair.secretKey);
225
+ }
226
+ async uploadSecret(secret) {
227
+ if (!this.options.walletAddress) {
228
+ console.error("signerAddress is not found");
229
+ return { status: "no-signer-address" };
230
+ }
231
+ const blindedShares = this.mpcClient.getBlindedShares(Buffer.from(secret, "utf8"));
232
+ const uploadRequest = this.mpcClient.uploadRequest(blindedShares);
233
+ const messageToSign = this.mpcClient.uploadMessageToSign(uploadRequest);
234
+ const signedMessage = await this.signTypedData(messageToSign.domain, messageToSign.types, messageToSign.value);
235
+ return this.mpcClient.uploadSecret(this.userId, uploadRequest, signedMessage, blindedShares);
236
+ }
237
+ async addAddressMessageToSign(address, publicKey, addressToAddType) {
238
+ return this.mpcClient.addAddressMessageToSign(address, publicKey, addressToAddType);
239
+ }
240
+ async removeAddressMessageToSign(address, publicKey, addressToRemoveType) {
241
+ return this.mpcClient.removeAddressMessageToSign(address, publicKey, addressToRemoveType);
242
+ }
243
+ async addAddressToMpcSecret(userId, message, signature) {
244
+ return this.mpcClient.addAddress(userId, message, signature);
245
+ }
246
+ async removeAddressFromMpcSecret(userId, message, signature) {
247
+ return this.mpcClient.removeAddress(userId, message, signature);
248
+ }
249
+ };
250
+ //#endregion
251
+ export { LocalEnclave };
252
+
253
+ //# sourceMappingURL=local.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.mjs","names":["MPCClient"],"sources":["../src/local.ts"],"sourcesContent":["import type { EncryptionPasswordStore } from \"@idos-network/kwil-infra/actions\";\n\nimport {\n base64Codec,\n base64Encode,\n hexDecode,\n hexEncode,\n utf8Decode,\n utf8Encode,\n} from \"@idos-network/utils/codecs\";\nimport { generatePassword } from \"@idos-network/utils/cryptography\";\nimport { decrypt, encrypt, keyDerivation } from \"@idos-network/utils/encryption\";\nimport { LocalStorageStore, type PipeCodecArgs, type Store } from \"@idos-network/utils/store\";\nimport { syncScrypt } from \"scrypt-js\";\nimport nacl from \"tweetnacl\";\n\nimport type {\n AddAddressMessageToSign,\n AddAddressSignatureMessage,\n DownloadMessageToSign,\n RemoveAddressMessageToSign,\n RemoveAddressSignatureMessage,\n UploadMessageToSign,\n} from \"./mpc/types\";\nimport type {\n EnclaveOptions,\n MPCPasswordContext,\n PasswordContext,\n PrivateEncryptionProfile,\n PublicEncryptionProfile,\n} from \"./types\";\n\nimport { BaseProvider } from \"./base\";\nimport { STORAGE_KEYS } from \"./keys\";\nimport { Client as MPCClient } from \"./mpc/client\";\n\nexport interface LocalEnclaveOptions extends EnclaveOptions {\n store?: Store;\n allowedEncryptionStores?: EncryptionPasswordStore[];\n mpcConfiguration?: {\n nodeUrl: string;\n contractAddress: string;\n numMalicious: number;\n numNodes: number;\n numToReconstruct: number;\n };\n}\n\nexport class LocalEnclave<\n K extends LocalEnclaveOptions = LocalEnclaveOptions,\n> extends BaseProvider<K> {\n protected allowedEncryptionStores: EncryptionPasswordStore[];\n\n // Store for data\n protected store: Store;\n protected storeBase64: Store;\n protected storeObfuscated: Store;\n protected storeObfuscatedBase64: Store;\n\n // In case of MPC usage\n protected mpcClientInstance?: MPCClient;\n\n // Stored key pair and user id for that key pair\n // those are most likely loaded from the store\n // during the load() method.\n protected storedEncryptionProfile?: PrivateEncryptionProfile;\n\n constructor(options: K) {\n super(options);\n\n // By default, we only allow password auth method\n this.allowedEncryptionStores = options.allowedEncryptionStores ?? [\"user\"];\n this.store = options.store ?? new LocalStorageStore();\n this.storeObfuscated = this.store.pipeCodec(this.userIdObfuscationCodec());\n this.storeBase64 = this.store.pipeCodec(base64Codec);\n this.storeObfuscatedBase64 = this.store\n .pipeCodec(this.userIdObfuscationCodec())\n .pipeCodec(base64Codec);\n\n if (options.mpcConfiguration) {\n this.mpcClientInstance = new MPCClient(\n options.mpcConfiguration.nodeUrl,\n options.mpcConfiguration.contractAddress,\n options.mpcConfiguration.numMalicious,\n options.mpcConfiguration.numNodes,\n options.mpcConfiguration.numToReconstruct,\n // TODO: This is weird, we should not be forcing this\n options.walletType ?? \"EVM\",\n options.walletAddress ?? \"\",\n options.walletPublicKey,\n );\n }\n }\n\n /** @override parent method to reset the enclave */\n async reset(): Promise<void> {\n await super.reset();\n this.storedEncryptionProfile = undefined;\n this.store.reset();\n }\n\n /** @override parent method to reconfigure the enclave */\n async reconfigure(options: Partial<K> = {}): Promise<void> {\n await super.reconfigure(options);\n // Reconfigure MPC client if any signer information changed\n if (this.mpcClientInstance && options.walletType && options.walletAddress) {\n this.mpcClientInstance.reconfigure(\n options.walletType,\n options.walletAddress ?? \"\",\n options.walletPublicKey,\n );\n }\n }\n\n /**\n * Return a codec that encrypts/decrypts data using a key derived from the provider's user ID.\n *\n * This ensures that data is minimally obfuscated to avoid low-sophistication attacks.\n */\n private userIdObfuscationCodec(): PipeCodecArgs<string> {\n // oxlint-disable-next-line typescript/no-this-alias -- Needed for `this` in nested encode/decode functions\n const self = this;\n\n const toKey = (userId: string, salt: Uint8Array) =>\n syncScrypt(utf8Encode(userId), salt, 16384, 8, 1, nacl.secretbox.keyLength);\n\n return {\n encode(data: string): string {\n if (!self.options.userId) {\n throw new Error(\"User ID required for encryption\");\n }\n\n const dataBytes = utf8Encode(data); // Convert string to Uint8Array\n const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);\n const salt = nacl.randomBytes(16);\n const key = toKey(self.options.userId, salt);\n const payload = nacl.secretbox(dataBytes, nonce, key);\n\n // Store salt + nonce + ciphertext\n const combined = new Uint8Array(salt.length + nonce.length + payload.length);\n combined.set(salt, 0);\n combined.set(nonce, salt.length);\n combined.set(payload, salt.length + nonce.length);\n\n return `0x${hexEncode(combined)}`;\n },\n\n decode(payload: string): string {\n if (!self.options.userId) {\n throw new Error(\"User ID required for decryption\");\n }\n\n if (payload.slice(0, 2) !== \"0x\") {\n throw new Error(`missing 0x prefix: ${payload}`);\n }\n\n const combined = hexDecode(payload.slice(2));\n const salt = combined.slice(0, 16);\n const nonce = combined.slice(16, 16 + nacl.secretbox.nonceLength);\n const ciphertext = combined.slice(16 + nacl.secretbox.nonceLength);\n\n const key = toKey(self.options.userId, salt);\n const result = nacl.secretbox.open(ciphertext, nonce, key);\n\n if (!result) throw new Error(\"Failed to decrypt data\");\n\n return utf8Decode(result); // Convert Uint8Array back to string\n },\n };\n }\n /** @see parent method extended with loading the profile from the store */\n async load(): Promise<void> {\n await super.load();\n\n const userId = await this.store.get<string>(STORAGE_KEYS.USER_ID);\n if (userId) this.options.userId = userId;\n\n let password = await this.storeObfuscated.get<string>(STORAGE_KEYS.OBFUSCATED_PASSWORD);\n if (!password) {\n password = await this.store.get<string>(STORAGE_KEYS.DEPRECATED___PASSWORD);\n if (!password) return;\n\n await this.storeObfuscated.set(STORAGE_KEYS.OBFUSCATED_PASSWORD, password);\n }\n await this.store.delete(STORAGE_KEYS.DEPRECATED___PASSWORD);\n\n let encryptionSecretKey = await this.storeObfuscatedBase64.get<Uint8Array>(\n STORAGE_KEYS.OBFUSCATED_BASE64_ENCRYPTION_SECRET_KEY,\n );\n if (!encryptionSecretKey) {\n encryptionSecretKey = await this.storeBase64.get<Uint8Array>(\n STORAGE_KEYS.DEPRECATED___ENCRYPTION_SECRET_KEY,\n );\n if (!encryptionSecretKey) return;\n\n await this.storeObfuscatedBase64.set(\n STORAGE_KEYS.OBFUSCATED_BASE64_ENCRYPTION_SECRET_KEY,\n encryptionSecretKey,\n );\n }\n await this.store.delete(STORAGE_KEYS.DEPRECATED___ENCRYPTION_SECRET_KEY);\n // Even older version.\n await this.store.delete(STORAGE_KEYS.DEPRECATED___ENCRYPTION_PRIVATE_KEY);\n\n if (!password || !userId || !encryptionSecretKey) {\n return;\n }\n\n let encryptionPasswordStore = await this.store.get<EncryptionPasswordStore>(\n STORAGE_KEYS.ENCRYPTION_PASSWORD_STORE,\n );\n\n // Migration from \"password\" to \"user\"\n // TODO: Remove this after a while\n if (!encryptionPasswordStore || (encryptionPasswordStore as string) === \"password\") {\n encryptionPasswordStore = \"user\";\n await this.store.set<EncryptionPasswordStore>(\n STORAGE_KEYS.ENCRYPTION_PASSWORD_STORE,\n encryptionPasswordStore,\n );\n }\n\n this.storedEncryptionProfile = {\n userId,\n password,\n keyPair: nacl.box.keyPair.fromSecretKey(encryptionSecretKey),\n encryptionPasswordStore,\n };\n }\n\n /**\n * Encrypts a message to a receiver.\n * This method also checks if the user is authorized to use the keys.\n *\n * @param message - The message to encrypt.\n * @param receiverPublicKey - The public key of the receiver.\n *\n * @returns The encrypted message.\n */\n async encrypt(\n message: Uint8Array,\n receiverPublicKey: Uint8Array,\n ): Promise<{ content: Uint8Array; encryptorPublicKey: Uint8Array }> {\n const { keyPair } = await this.getPrivateEncryptionProfile();\n return encrypt(message, keyPair.publicKey, receiverPublicKey);\n }\n\n /**\n * Decrypts a message from a sender.\n * This method also checks if the user is authorized to use the keys.\n *\n * @param message - The message to decrypt.\n * @param senderPublicKey - The public key of the sender.\n *\n * @returns The decrypted message.\n */\n async decrypt(\n message: Uint8Array,\n senderPublicKey: Uint8Array,\n ): Promise<Uint8Array<ArrayBufferLike>> {\n const { keyPair } = await this.getPrivateEncryptionProfile();\n return decrypt(message, keyPair, senderPublicKey);\n }\n\n /**\n * @see BaseProvider#getPrivateEncryptionProfile\n */\n async getPrivateEncryptionProfile(skipGuard = false): Promise<PrivateEncryptionProfile> {\n // In case there is a no key pair, which matches we don't need a new one.\n if (this.storedEncryptionProfile) {\n let canBeUsed = this.storedEncryptionProfile.userId === this.userId;\n\n if (canBeUsed && !skipGuard) {\n // When users matches, we also need to check\n // if origin is authorized to use the keys.\n canBeUsed = await this.guardKeys();\n }\n\n if (canBeUsed) {\n return this.storedEncryptionProfile;\n }\n\n // Something did not match, we need to create a new key pair\n // and reset the enclave.\n await this.reset();\n }\n\n // The stored profile can't be used, or we have to create a new one.\n let password: string | undefined;\n let encryptionPasswordStore: EncryptionPasswordStore | undefined;\n\n const context = await this.getPasswordContext();\n\n if (context.encryptionPasswordStore === \"user\") {\n await this.store.setRememberDuration(context.duration);\n\n password = context.password;\n encryptionPasswordStore = context.encryptionPasswordStore;\n }\n\n if (context.encryptionPasswordStore === \"mpc\") {\n // TODO: This is resetting duration, but should?\n await this.store.setRememberDuration(undefined);\n\n password = await this.ensureMPCPassword();\n encryptionPasswordStore = \"mpc\";\n }\n\n if (!password || !encryptionPasswordStore) {\n throw new Error(\"Password or encryption password store is not found\");\n }\n\n return this.createEncryptionProfileFromPassword(password, this.userId, encryptionPasswordStore);\n }\n\n /** @see BaseProvider#ensureUserEncryptionProfile */\n async ensureUserEncryptionProfile(): Promise<PublicEncryptionProfile> {\n const { keyPair, encryptionPasswordStore, userId } = await this.getPrivateEncryptionProfile();\n\n return {\n userId,\n userEncryptionPublicKey: base64Encode(keyPair.publicKey),\n encryptionPasswordStore: encryptionPasswordStore,\n };\n }\n\n /**\n * This method needs to check `options` and should derive the password context from it.\n *\n * @returns The password context.\n */\n async getPasswordContext(): Promise<PasswordContext | MPCPasswordContext> {\n throw new Error(\"Method 'getPasswordContext' has to be implemented in the subclass.\");\n }\n\n /**\n * Creates and store encryption profile from a password.\n *\n * @param password - The password to use.\n * @param userId - The user id to use.\n * @param encryptionPasswordStore - The encryption password store to use.\n *\n * @returns The encryption profile.\n */\n async createEncryptionProfileFromPassword(\n password: string,\n userId: string,\n encryptionPasswordStore: EncryptionPasswordStore,\n ): Promise<PrivateEncryptionProfile> {\n const secretKey = await keyDerivation(password, userId);\n\n const keyPair = nacl.box.keyPair.fromSecretKey(secretKey);\n\n await this.store.set(STORAGE_KEYS.USER_ID, userId);\n await this.storeObfuscated.set(STORAGE_KEYS.OBFUSCATED_PASSWORD, password);\n await this.store.delete(STORAGE_KEYS.DEPRECATED___PASSWORD);\n await this.store.set(STORAGE_KEYS.ENCRYPTION_PASSWORD_STORE, encryptionPasswordStore);\n await this.storeObfuscatedBase64.set(\n STORAGE_KEYS.OBFUSCATED_BASE64_ENCRYPTION_SECRET_KEY,\n keyPair.secretKey,\n );\n await this.store.delete(STORAGE_KEYS.DEPRECATED___ENCRYPTION_SECRET_KEY);\n await this.storeBase64.set(STORAGE_KEYS.ENCRYPTION_PUBLIC_KEY, keyPair.publicKey);\n\n this.storedEncryptionProfile = {\n userId,\n password,\n keyPair,\n encryptionPasswordStore,\n };\n\n return this.storedEncryptionProfile;\n }\n\n protected async ensureMPCPassword(): Promise<string> {\n if (this.options?.mode !== \"new\") {\n const { status: downloadStatus, secret: downloadedPassword } = await this.downloadSecret();\n\n if (downloadStatus === \"ok\" && downloadedPassword) {\n return utf8Decode(downloadedPassword);\n }\n\n throw Error(\"A secret might be stored at MPC ZK nodes, but can't be obtained\");\n }\n\n const password = generatePassword();\n const { status: uploadStatus } = await this.uploadSecret(password);\n\n if (uploadStatus !== \"success\") {\n throw Error(`A secret upload failed with status: ${uploadStatus}`);\n }\n\n return password;\n }\n\n private get mpcClient(): MPCClient {\n if (!this.mpcClientInstance) {\n throw new Error(\"MPC client is not initialized\");\n }\n return this.mpcClientInstance;\n }\n\n private async downloadSecret(): Promise<{\n status: string;\n secret: Buffer<ArrayBufferLike> | undefined;\n }> {\n // I really don't like this, I guess the walletAddress should be stored in the store.\n if (!this.options.walletAddress) {\n throw new Error(\"walletAddress is not found\");\n }\n\n const ephemeralKeyPair = nacl.box.keyPair();\n\n const downloadRequest = this.mpcClient.downloadRequest(ephemeralKeyPair.publicKey);\n\n const messageToSign = this.mpcClient.downloadMessageToSign(\n downloadRequest,\n ) as DownloadMessageToSign;\n\n const signedMessage = await this.signTypedData(\n messageToSign.domain,\n messageToSign.types,\n messageToSign.value,\n );\n\n return this.mpcClient.downloadSecret(\n this.userId,\n downloadRequest,\n signedMessage,\n ephemeralKeyPair.secretKey,\n );\n }\n\n private async uploadSecret(secret: string): Promise<{ status: string }> {\n if (!this.options.walletAddress) {\n console.error(\"signerAddress is not found\");\n return { status: \"no-signer-address\" };\n }\n\n const blindedShares = this.mpcClient.getBlindedShares(Buffer.from(secret, \"utf8\"));\n const uploadRequest = this.mpcClient.uploadRequest(blindedShares);\n const messageToSign = this.mpcClient.uploadMessageToSign(uploadRequest) as UploadMessageToSign;\n\n const signedMessage = await this.signTypedData(\n // oxlint-disable-next-line typescript/no-explicit-any -- TODO: Change this when we know how to MPC & other chains\n messageToSign.domain as any,\n // oxlint-disable-next-line typescript/no-explicit-any -- TODO: Change this when we know how to MPC & other chains\n messageToSign.types as any,\n // oxlint-disable-next-line typescript/no-explicit-any -- TODO: Change this when we know how to MPC & other chains\n messageToSign.value as any,\n );\n\n return this.mpcClient.uploadSecret(this.userId, uploadRequest, signedMessage, blindedShares);\n }\n\n async addAddressMessageToSign(\n address: string,\n publicKey: string | undefined,\n addressToAddType: string,\n ): Promise<AddAddressMessageToSign> {\n return this.mpcClient.addAddressMessageToSign(\n address,\n publicKey,\n addressToAddType,\n ) as AddAddressMessageToSign;\n }\n\n async removeAddressMessageToSign(\n address: string,\n publicKey: string | undefined,\n addressToRemoveType: string,\n ): Promise<RemoveAddressMessageToSign> {\n return this.mpcClient.removeAddressMessageToSign(\n address,\n publicKey,\n addressToRemoveType,\n ) as RemoveAddressMessageToSign;\n }\n\n async addAddressToMpcSecret(\n userId: string,\n message: AddAddressSignatureMessage,\n signature: string,\n ): Promise<string> {\n return this.mpcClient.addAddress(userId, message, signature);\n }\n\n async removeAddressFromMpcSecret(\n userId: string,\n message: RemoveAddressSignatureMessage,\n signature: string,\n ): Promise<string> {\n return this.mpcClient.removeAddress(userId, message, signature);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { C as UpdateWalletsSignatureMessage, S as UpdateWalletsRequest, T as UploadSignatureMessage, _ as RemoveAddressRequest, a as Address, b as UPDATE_TYPES, c as Bytes32, d as DownloadRequest, f as DownloadSignatureMessage, g as RemoveAddressMessageToSign, h as REMOVE_ADDRESS_TYPES, i as AddAddressSignatureMessage, l as DOWNLOAD_TYPES, m as PbcAddress, n as AddAddressMessageToSign, o as Bytes, p as EncryptedShare, r as AddAddressRequest, s as Bytes24, t as ADD_ADDRESS_TYPES, u as DownloadMessageToSign, v as RemoveAddressSignatureMessage, w as UploadMessageToSign, x as UPLOAD_TYPES, y as Sharing } from "../types-DKsOwtWL.mjs";
2
+ import { t as Client } from "../client-Bu0aO5sT.mjs";
3
+ export { ADD_ADDRESS_TYPES, AddAddressMessageToSign, AddAddressRequest, AddAddressSignatureMessage, Address, Bytes, Bytes24, Bytes32, Client, DOWNLOAD_TYPES, DownloadMessageToSign, DownloadRequest, DownloadSignatureMessage, EncryptedShare, PbcAddress, REMOVE_ADDRESS_TYPES, RemoveAddressMessageToSign, RemoveAddressRequest, RemoveAddressSignatureMessage, Sharing, UPDATE_TYPES, UPLOAD_TYPES, UpdateWalletsRequest, UpdateWalletsSignatureMessage, UploadMessageToSign, UploadSignatureMessage };
@@ -0,0 +1,2 @@
1
+ import { a as UPDATE_TYPES, i as REMOVE_ADDRESS_TYPES, n as ADD_ADDRESS_TYPES, o as UPLOAD_TYPES, r as DOWNLOAD_TYPES, t as Client } from "../client-BSkUuHYm.mjs";
2
+ export { ADD_ADDRESS_TYPES, Client, DOWNLOAD_TYPES, REMOVE_ADDRESS_TYPES, UPDATE_TYPES, UPLOAD_TYPES };
@@ -0,0 +1,73 @@
1
+ import { TypedDataDomain, TypedDataField } from "ethers";
2
+
3
+ //#region src/mpc/types.d.ts
4
+ type PbcAddress = string;
5
+ type Bytes32 = string;
6
+ type Bytes24 = string;
7
+ type Address = string;
8
+ type Bytes = string;
9
+ declare const UPLOAD_TYPES: Record<string, TypedDataField[]>;
10
+ declare const DOWNLOAD_TYPES: Record<string, TypedDataField[]>;
11
+ declare const UPDATE_TYPES: Record<string, TypedDataField[]>;
12
+ declare const ADD_ADDRESS_TYPES: Record<string, TypedDataField[]>;
13
+ declare const REMOVE_ADDRESS_TYPES: Record<string, TypedDataField[]>;
14
+ interface UploadSignatureMessage {
15
+ share_commitments: Bytes32[];
16
+ recovering_addresses: Address[];
17
+ }
18
+ interface Sharing {
19
+ share_commitments: Bytes32[];
20
+ recovering_addresses: Address[];
21
+ share_data: Bytes;
22
+ }
23
+ interface DownloadSignatureMessage {
24
+ recovering_address: Address;
25
+ timestamp: number;
26
+ public_key: Bytes32;
27
+ }
28
+ type DownloadRequest = DownloadSignatureMessage;
29
+ interface AddAddressSignatureMessage {
30
+ recovering_address: Address;
31
+ address_to_add: Address;
32
+ timestamp: number;
33
+ }
34
+ type AddAddressRequest = AddAddressSignatureMessage;
35
+ interface RemoveAddressSignatureMessage {
36
+ recovering_address: Address;
37
+ address_to_remove: Address;
38
+ timestamp: number;
39
+ }
40
+ type RemoveAddressRequest = RemoveAddressSignatureMessage;
41
+ interface UpdateWalletsSignatureMessage {
42
+ recovering_addresses: Address[];
43
+ timestamp: number;
44
+ }
45
+ type UpdateWalletsRequest = UpdateWalletsSignatureMessage;
46
+ interface EncryptedShare {
47
+ encrypted_share: Bytes;
48
+ public_key: Bytes32;
49
+ nonce: Bytes24;
50
+ }
51
+ type DownloadMessageToSign = {
52
+ domain: TypedDataDomain;
53
+ types: Record<string, TypedDataField[]>;
54
+ value: DownloadSignatureMessage;
55
+ };
56
+ type UploadMessageToSign = {
57
+ domain: TypedDataDomain;
58
+ types: Record<string, TypedDataField[]>;
59
+ value: UploadSignatureMessage;
60
+ };
61
+ type AddAddressMessageToSign = {
62
+ domain: TypedDataDomain;
63
+ types: Record<string, TypedDataField[]>;
64
+ value: AddAddressSignatureMessage;
65
+ };
66
+ type RemoveAddressMessageToSign = {
67
+ domain: TypedDataDomain;
68
+ types: Record<string, TypedDataField[]>;
69
+ value: RemoveAddressSignatureMessage;
70
+ };
71
+ //#endregion
72
+ export { UpdateWalletsSignatureMessage as C, UpdateWalletsRequest as S, UploadSignatureMessage as T, RemoveAddressRequest as _, Address as a, UPDATE_TYPES as b, Bytes32 as c, DownloadRequest as d, DownloadSignatureMessage as f, RemoveAddressMessageToSign as g, REMOVE_ADDRESS_TYPES as h, AddAddressSignatureMessage as i, DOWNLOAD_TYPES as l, PbcAddress as m, AddAddressMessageToSign as n, Bytes as o, EncryptedShare as p, AddAddressRequest as r, Bytes24 as s, ADD_ADDRESS_TYPES as t, DownloadMessageToSign as u, RemoveAddressSignatureMessage as v, UploadMessageToSign as w, UPLOAD_TYPES as x, Sharing as y };
73
+ //# sourceMappingURL=types-DKsOwtWL.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DKsOwtWL.d.mts","names":[],"sources":["../src/mpc/types.ts"],"mappings":";;;KAEY,UAAA;AAAA,KACA,OAAA;AAAA,KACA,OAAA;AAAA,KACA,OAAA;AAAA,KACA,KAAA;AAAA,cAEC,YAAA,EAAc,MAAA,SAAe,cAAA;AAAA,cAO7B,cAAA,EAAgB,MAAA,SAAe,cAAA;AAAA,cAQ/B,YAAA,EAAc,MAAA,SAAe,cAAA;AAAA,cAO7B,iBAAA,EAAmB,MAAA,SAAe,cAAA;AAAA,cAQlC,oBAAA,EAAsB,MAAA,SAAe,cAAA;AAAA,UAQjC,sBAAA;EACf,iBAAA,EAAmB,OAAA;EACnB,oBAAA,EAAsB,OAAA;AAAA;AAAA,UAGP,OAAA;EACf,iBAAA,EAAmB,OAAA;EACnB,oBAAA,EAAsB,OAAA;EACtB,UAAA,EAAY,KAAA;AAAA;AAAA,UAGG,wBAAA;EACf,kBAAA,EAAoB,OAAA;EACpB,SAAA;EACA,UAAA,EAAY,OAAA;AAAA;AAAA,KAGF,eAAA,GAAkB,wBAAA;AAAA,UAEb,0BAAA;EACf,kBAAA,EAAoB,OAAA;EACpB,cAAA,EAAgB,OAAA;EAChB,SAAA;AAAA;AAAA,KAGU,iBAAA,GAAoB,0BAAA;AAAA,UAEf,6BAAA;EACf,kBAAA,EAAoB,OAAA;EACpB,iBAAA,EAAmB,OAAA;EACnB,SAAA;AAAA;AAAA,KAGU,oBAAA,GAAuB,6BAAA;AAAA,UAElB,6BAAA;EACf,oBAAA,EAAsB,OAAA;EACtB,SAAA;AAAA;AAAA,KAGU,oBAAA,GAAuB,6BAAA;AAAA,UAElB,cAAA;EACf,eAAA,EAAiB,KAAA;EACjB,UAAA,EAAY,OAAA;EACZ,KAAA,EAAO,OAAA;AAAA;AAAA,KAGG,qBAAA;EACV,MAAA,EAAQ,eAAA;EACR,KAAA,EAAO,MAAA,SAAe,cAAA;EACtB,KAAA,EAAO,wBAAA;AAAA;AAAA,KAGG,mBAAA;EACV,MAAA,EAAQ,eAAA;EACR,KAAA,EAAO,MAAA,SAAe,cAAA;EACtB,KAAA,EAAO,sBAAA;AAAA;AAAA,KAGG,uBAAA;EACV,MAAA,EAAQ,eAAA;EACR,KAAA,EAAO,MAAA,SAAe,cAAA;EACtB,KAAA,EAAO,0BAAA;AAAA;AAAA,KAGG,0BAAA;EACV,MAAA,EAAQ,eAAA;EACR,KAAA,EAAO,MAAA,SAAe,cAAA;EACtB,KAAA,EAAO,6BAAA;AAAA"}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@idos-network/enclave",
3
+ "version": "1.1.0",
4
+ "description": "idOS Enclave JavaScript SDK",
5
+ "homepage": "https://idos.network",
6
+ "license": "MIT",
7
+ "repository": "github:idos-network/idos-sdk-js",
8
+ "files": [
9
+ "dist/**/*",
10
+ "src/**/*"
11
+ ],
12
+ "type": "module",
13
+ "sideEffects": false,
14
+ "main": "./dist/index.mjs",
15
+ "types": "./dist/index.d.mts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.mts",
19
+ "import": "./dist/index.mjs"
20
+ },
21
+ "./local": {
22
+ "types": "./dist/local.d.mts",
23
+ "import": "./dist/local.mjs"
24
+ },
25
+ "./mpc": {
26
+ "types": "./dist/mpc/index.d.mts",
27
+ "import": "./dist/mpc/index.mjs"
28
+ }
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "dependencies": {
34
+ "scrypt-js": "^3.0.1",
35
+ "tiny-invariant": "^1.3.3",
36
+ "tweetnacl": "^1.0.3",
37
+ "zod": "4.3.6",
38
+ "@idos-network/credentials": "1.1.0",
39
+ "@idos-network/utils": "1.1.0",
40
+ "@idos-network/kwil-infra": "1.1.0"
41
+ },
42
+ "devDependencies": {
43
+ "@types/chrome": "^0.1.0",
44
+ "@types/node": "25.5.2",
45
+ "jsdom": "^22.1.0",
46
+ "tsdown": "^0.21.0",
47
+ "typescript": "^5.8.3",
48
+ "vitest": "4.1.4"
49
+ },
50
+ "peerDependencies": {
51
+ "@partisiablockchain/abi-client": "^5.207.0",
52
+ "@partisiablockchain/blockchain-api-transaction-client": "^5.149.0",
53
+ "ethers": "^6.14.0"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "@partisiablockchain/blockchain-api-transaction-client": {
57
+ "optional": true
58
+ },
59
+ "@partisiablockchain/abi-client": {
60
+ "optional": true
61
+ },
62
+ "ethers": {
63
+ "optional": true
64
+ }
65
+ },
66
+ "engines": {
67
+ "node": ">=22.19.0"
68
+ },
69
+ "scripts": {
70
+ "build": "tsdown",
71
+ "dev": "tsdown --watch",
72
+ "publint": "pnpx publint --strict",
73
+ "test": "vitest",
74
+ "typecheck": "tsc --noEmit"
75
+ }
76
+ }
@@ -0,0 +1,137 @@
1
+ import type { idOSCredential } from "@idos-network/credentials/types";
2
+
3
+ import { base64Encode, utf8Encode } from "@idos-network/utils/codecs";
4
+ import { describe, expect, it, vi } from "vitest";
5
+
6
+ import type { PublicEncryptionProfile } from "./types.js";
7
+
8
+ import { BaseProvider } from "./base.js";
9
+
10
+ type TestOptions = { userId?: string };
11
+
12
+ class TestProvider extends BaseProvider<TestOptions> {
13
+ async decrypt(message: Uint8Array): Promise<Uint8Array> {
14
+ return message;
15
+ }
16
+
17
+ async ensureUserEncryptionProfile(): Promise<PublicEncryptionProfile> {
18
+ return {
19
+ userId: crypto.randomUUID(),
20
+ userEncryptionPublicKey: base64Encode(new Uint8Array([1, 2, 3])),
21
+ encryptionPasswordStore: "user",
22
+ };
23
+ }
24
+ }
25
+
26
+ describe("BaseProvider", () => {
27
+ it("uses signTypedData when available", async () => {
28
+ const provider = new TestProvider({ userId: "user" });
29
+ const signTypedData = vi.fn().mockResolvedValue("sig");
30
+ provider.setSigner({ signTypedData });
31
+
32
+ const result = await provider.signTypedData({ domain: 1 }, { types: 2 }, { value: 3 });
33
+
34
+ expect(result).toBe("sig");
35
+ expect(signTypedData).toHaveBeenCalledWith({ domain: 1 }, { types: 2 }, { value: 3 });
36
+ });
37
+
38
+ it("falls back to signMessage and extracts signedMessage", async () => {
39
+ const provider = new TestProvider({ userId: "user" });
40
+ const signMessage = vi.fn().mockResolvedValue({ result: { signedMessage: "sig" } });
41
+ provider.setSigner({ signMessage });
42
+
43
+ const result = await provider.signTypedData({}, {}, { hello: "world" });
44
+
45
+ expect(result).toBe("sig");
46
+ expect(signMessage).toHaveBeenCalledWith(JSON.stringify({ hello: "world" }));
47
+ });
48
+
49
+ it("accepts signMessage string response", async () => {
50
+ const provider = new TestProvider({ userId: "user" });
51
+ const signMessage = vi.fn().mockResolvedValue("sig");
52
+ provider.setSigner({ signMessage });
53
+
54
+ await expect(provider.signTypedData({}, {}, { ok: true })).resolves.toBe("sig");
55
+ });
56
+
57
+ it("throws when signer is not set", async () => {
58
+ const provider = new TestProvider({ userId: "user" });
59
+ await expect(provider.signTypedData({}, {}, {})).rejects.toThrow("Signer is not set");
60
+ });
61
+
62
+ it("throws when no sign method is provided", () => {
63
+ const provider = new TestProvider({ userId: "user" });
64
+ expect(() => provider.setSigner({} as unknown as Record<string, never>)).toThrow(
65
+ "No sign method found in passed signer",
66
+ );
67
+ });
68
+
69
+ it("requires userId in options for userId getter", () => {
70
+ const provider = new TestProvider({});
71
+ expect(() => provider.userId).toThrow("User ID is not present");
72
+ });
73
+
74
+ it("filters credentials and strips content", async () => {
75
+ const provider = new TestProvider({ userId: "user" });
76
+ const publicKey = base64Encode(new Uint8Array([1, 2, 3]));
77
+
78
+ const matches = { type: "kyc", level: "basic" };
79
+ const misses = { type: "aml", level: "basic" };
80
+
81
+ const credentials: idOSCredential[] = [
82
+ {
83
+ id: "cred-1",
84
+ user_id: "user-1",
85
+ public_notes: "{}",
86
+ content: base64Encode(utf8Encode(JSON.stringify(matches))),
87
+ encryptor_public_key: publicKey,
88
+ issuer_auth_public_key: "issuer",
89
+ },
90
+ {
91
+ id: "cred-2",
92
+ user_id: "user-1",
93
+ public_notes: "{}",
94
+ content: base64Encode(utf8Encode(JSON.stringify(misses))),
95
+ encryptor_public_key: publicKey,
96
+ issuer_auth_public_key: "issuer",
97
+ },
98
+ ];
99
+
100
+ const filtered = await provider.filterCredentials(credentials, {
101
+ pick: { type: ["kyc"] },
102
+ omit: {},
103
+ });
104
+
105
+ expect(filtered).toHaveLength(1);
106
+ expect(filtered[0]?.id).toBe("cred-1");
107
+ expect(filtered[0]?.content).toBe("");
108
+ });
109
+
110
+ it("returns all credentials when no filters are provided", async () => {
111
+ const provider = new TestProvider({ userId: "user" });
112
+ const publicKey = base64Encode(new Uint8Array([1, 2, 3]));
113
+ const credentials: idOSCredential[] = [
114
+ {
115
+ id: "cred-1",
116
+ user_id: "user-1",
117
+ public_notes: "{}",
118
+ content: base64Encode(utf8Encode(JSON.stringify({ value: 1 }))),
119
+ encryptor_public_key: publicKey,
120
+ issuer_auth_public_key: "issuer",
121
+ },
122
+ {
123
+ id: "cred-2",
124
+ user_id: "user-1",
125
+ public_notes: "{}",
126
+ content: base64Encode(utf8Encode(JSON.stringify({ value: 2 }))),
127
+ encryptor_public_key: publicKey,
128
+ issuer_auth_public_key: "issuer",
129
+ },
130
+ ];
131
+
132
+ const filtered = await provider.filterCredentials(credentials, { pick: {}, omit: {} });
133
+
134
+ expect(filtered).toHaveLength(2);
135
+ expect(filtered.every((credential) => credential.content === "")).toBe(true);
136
+ });
137
+ });