@zama-fhe/relayer-sdk 0.2.0-5 → 0.2.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.
Binary file
package/lib/node.cjs CHANGED
@@ -57,6 +57,32 @@ const bytesToBigInt = function (byteArray) {
57
57
  return BigInt(`0x${hex}`);
58
58
  };
59
59
 
60
+ function setAuth(init, auth) {
61
+ if (auth) {
62
+ switch (auth.__type) {
63
+ case 'BearerToken':
64
+ init.headers['Authorization'] =
65
+ `Bearer ${auth.token}`;
66
+ break;
67
+ case 'ApiKeyHeader':
68
+ init.headers[auth.header || 'x-api-key'] =
69
+ auth.value;
70
+ break;
71
+ case 'ApiKeyCookie':
72
+ if (typeof window !== 'undefined') {
73
+ document.cookie = `${auth.cookie || 'x-api-key'}=${auth.value}; path=/; SameSite=Lax; Secure; HttpOnly;`;
74
+ init.credentials = 'include';
75
+ }
76
+ else {
77
+ let cookie = `${auth.cookie || 'x-api-key'}=${auth.value};`;
78
+ init.headers['Cookie'] = cookie;
79
+ }
80
+ break;
81
+ }
82
+ }
83
+ return init;
84
+ }
85
+
60
86
  function getErrorCause(e) {
61
87
  if (e instanceof Error && typeof e.cause === 'object' && e.cause !== null) {
62
88
  return e.cause;
@@ -238,14 +264,13 @@ function assertIsRelayerFetchResponseJson(json) {
238
264
  }
239
265
  }
240
266
  async function fetchRelayerJsonRpcPost(relayerOperation, url, payload, options) {
241
- const init = {
267
+ const init = setAuth({
242
268
  method: 'POST',
243
269
  headers: {
244
270
  'Content-Type': 'application/json',
245
- ...(options?.apiKey && { 'x-api-key': options.apiKey }),
246
271
  },
247
272
  body: JSON.stringify(payload),
248
- };
273
+ }, options?.auth);
249
274
  let response;
250
275
  let json;
251
276
  try {
@@ -615,7 +640,7 @@ function checkDeadlineValidity(startTimestamp, durationDays) {
615
640
  throw Error('User decrypt request has expired');
616
641
  }
617
642
  }
618
- const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, options) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays) => {
643
+ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, instanceOptions) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays, options) => {
619
644
  const extraData = '0x00';
620
645
  let pubKey;
621
646
  let privKey;
@@ -674,7 +699,7 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
674
699
  publicKey: publicKeySanitized,
675
700
  extraData,
676
701
  };
677
- const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', `${relayerUrl}/v1/user-decrypt`, payloadForRequest, options);
702
+ const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', `${relayerUrl}/v1/user-decrypt`, payloadForRequest, instanceOptions ?? options);
678
703
  // assume the KMS Signers have the correct order
679
704
  let indexedKmsSigners = kmsSigners.map((signer, index) => {
680
705
  return TKMS.new_server_id_addr(index + 1, signer);
@@ -956,7 +981,7 @@ function isFhevmRelayerInputProofResponse(json) {
956
981
  return (response.signatures.every((s) => typeof s === 'string') &&
957
982
  response.handles.every((h) => typeof h === 'string'));
958
983
  }
959
- const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerUrl, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners) => (contractAddress, userAddress) => {
984
+ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerUrl, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners, instanceOptions) => (contractAddress, userAddress) => {
960
985
  if (!ethers.isAddress(contractAddress)) {
961
986
  throw new Error('Contract address is not a valid address.');
962
987
  }
@@ -1019,7 +1044,7 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
1019
1044
  contractChainId: ('0x' + chainId.toString(16)),
1020
1045
  extraData,
1021
1046
  };
1022
- const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', `${relayerUrl}/v1/input-proof`, payload, options);
1047
+ const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', `${relayerUrl}/v1/input-proof`, payload, options ?? instanceOptions);
1023
1048
  if (!isFhevmRelayerInputProofResponse(json)) {
1024
1049
  throwRelayerInternalError('INPUT_PROOF', json);
1025
1050
  }
@@ -1141,7 +1166,7 @@ function deserializeDecryptedResult(handles, decryptedResult) {
1141
1166
  handles.forEach((handle, idx) => (results[handle] = rawValues[idx]));
1142
1167
  return results;
1143
1168
  }
1144
- const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, options) => async (_handles) => {
1169
+ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, instanceOptions) => async (_handles, options) => {
1145
1170
  const extraData = '0x00';
1146
1171
  const acl = new ethers.ethers.Contract(aclContractAddress, aclABI, provider);
1147
1172
  let handles;
@@ -1166,7 +1191,7 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
1166
1191
  ciphertextHandles: handles,
1167
1192
  extraData,
1168
1193
  };
1169
- const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', `${relayerUrl}/v1/public-decrypt`, payloadForRequest, options);
1194
+ const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', `${relayerUrl}/v1/public-decrypt`, payloadForRequest, options ?? instanceOptions);
1170
1195
  // verify signatures on decryption:
1171
1196
  const domain = {
1172
1197
  name: 'Decryption',
@@ -1186,9 +1211,10 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
1186
1211
  ? result.decrypted_value
1187
1212
  : `0x${result.decrypted_value}`;
1188
1213
  const signatures = result.signatures;
1214
+ const signedExtraData = '0x';
1189
1215
  const recoveredAddresses = signatures.map((signature) => {
1190
1216
  const sig = signature.startsWith('0x') ? signature : `0x${signature}`;
1191
- const recoveredAddress = ethers.ethers.verifyTypedData(domain, types, { ctHandles: handles, decryptedResult, extraData }, sig);
1217
+ const recoveredAddress = ethers.ethers.verifyTypedData(domain, types, { ctHandles: handles, decryptedResult, extraData: signedExtraData }, sig);
1192
1218
  return recoveredAddress;
1193
1219
  });
1194
1220
  const thresholdReached = isThresholdReached(kmsSigners, recoveredAddresses, thresholdSigners);
@@ -1329,7 +1355,7 @@ const SepoliaConfig = {
1329
1355
  relayerUrl: 'https://relayer.testnet.zama.cloud',
1330
1356
  };
1331
1357
  const createInstance = async (config) => {
1332
- const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, } = config;
1358
+ const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, auth, } = config;
1333
1359
  if (!kmsContractAddress || !ethers.isAddress(kmsContractAddress)) {
1334
1360
  throw new Error('KMS contract address is not valid or empty');
1335
1361
  }
@@ -1361,8 +1387,8 @@ const createInstance = async (config) => {
1361
1387
  createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, cleanURL(config.relayerUrl), publicKeyData.publicKey, publicParamsData, coprocessorSigners, thresholdCoprocessorSigners),
1362
1388
  generateKeypair,
1363
1389
  createEIP712: createEIP712(verifyingContractAddressDecryption, chainId),
1364
- publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
1365
- userDecrypt: userDecryptRequest(kmsSigners, gatewayChainId, chainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
1390
+ publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider, auth && { auth }),
1391
+ userDecrypt: userDecryptRequest(kmsSigners, gatewayChainId, chainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider, auth && { auth }),
1366
1392
  getPublicKey: () => publicKeyData.publicKey
1367
1393
  ? {
1368
1394
  publicKey: publicKeyData.publicKey.safe_serialize(SERIALIZED_SIZE_LIMIT_PK),
package/lib/node.d.ts CHANGED
@@ -3,6 +3,56 @@ import { Eip1193Provider } from 'ethers';
3
3
  import { TfheClientKey } from 'node-tfhe';
4
4
  import { TfheCompactPublicKey } from 'node-tfhe';
5
5
 
6
+ /**
7
+ * Custom cookie authentication
8
+ */
9
+ declare type ApiKeyCookie = {
10
+ __type: 'ApiKeyCookie';
11
+ /**
12
+ * The cookie name. The default value is `x-api-key`.
13
+ */
14
+ cookie?: string;
15
+ /**
16
+ * The API key.
17
+ */
18
+ value: string;
19
+ };
20
+
21
+ /**
22
+ * Custom header authentication
23
+ */
24
+ declare type ApiKeyHeader = {
25
+ __type: 'ApiKeyHeader';
26
+ /**
27
+ * The header name. The default value is `x-api-key`.
28
+ */
29
+ header?: string;
30
+ /**
31
+ * The API key.
32
+ */
33
+ value: string;
34
+ };
35
+
36
+ /**
37
+ * Set the authentication method for the request. The default is no authentication.
38
+ * It supports:
39
+ * - Bearer Token
40
+ * - Custom header
41
+ * - Custom cookie
42
+ */
43
+ declare type Auth = BearerToken | ApiKeyHeader | ApiKeyCookie;
44
+
45
+ /**
46
+ * Bearer Token Authentication
47
+ */
48
+ declare type BearerToken = {
49
+ __type: 'BearerToken';
50
+ /**
51
+ * The Bearer token.
52
+ */
53
+ token: string;
54
+ };
55
+
6
56
  /**
7
57
  * Creates an EIP712 structure specifically for user decrypt requests
8
58
  *
@@ -99,6 +149,7 @@ export declare type FhevmInstanceConfig = {
99
149
  data: Uint8Array | null;
100
150
  id: string | null;
101
151
  };
152
+ auth?: Auth;
102
153
  };
103
154
 
104
155
  export declare const generateKeypair: () => {
@@ -133,7 +184,7 @@ export declare type RelayerEncryptedInput = {
133
184
  addAddress: (value: string) => RelayerEncryptedInput;
134
185
  getBits: () => EncryptionTypes[];
135
186
  encrypt: (options?: {
136
- apiKey?: string;
187
+ auth?: Auth;
137
188
  }) => Promise<{
138
189
  handles: Uint8Array[];
139
190
  inputProof: Uint8Array;
package/lib/node.js CHANGED
@@ -36,6 +36,32 @@ const bytesToBigInt = function (byteArray) {
36
36
  return BigInt(`0x${hex}`);
37
37
  };
38
38
 
39
+ function setAuth(init, auth) {
40
+ if (auth) {
41
+ switch (auth.__type) {
42
+ case 'BearerToken':
43
+ init.headers['Authorization'] =
44
+ `Bearer ${auth.token}`;
45
+ break;
46
+ case 'ApiKeyHeader':
47
+ init.headers[auth.header || 'x-api-key'] =
48
+ auth.value;
49
+ break;
50
+ case 'ApiKeyCookie':
51
+ if (typeof window !== 'undefined') {
52
+ document.cookie = `${auth.cookie || 'x-api-key'}=${auth.value}; path=/; SameSite=Lax; Secure; HttpOnly;`;
53
+ init.credentials = 'include';
54
+ }
55
+ else {
56
+ let cookie = `${auth.cookie || 'x-api-key'}=${auth.value};`;
57
+ init.headers['Cookie'] = cookie;
58
+ }
59
+ break;
60
+ }
61
+ }
62
+ return init;
63
+ }
64
+
39
65
  function getErrorCause(e) {
40
66
  if (e instanceof Error && typeof e.cause === 'object' && e.cause !== null) {
41
67
  return e.cause;
@@ -217,14 +243,13 @@ function assertIsRelayerFetchResponseJson(json) {
217
243
  }
218
244
  }
219
245
  async function fetchRelayerJsonRpcPost(relayerOperation, url, payload, options) {
220
- const init = {
246
+ const init = setAuth({
221
247
  method: 'POST',
222
248
  headers: {
223
249
  'Content-Type': 'application/json',
224
- ...(options?.apiKey && { 'x-api-key': options.apiKey }),
225
250
  },
226
251
  body: JSON.stringify(payload),
227
- };
252
+ }, options?.auth);
228
253
  let response;
229
254
  let json;
230
255
  try {
@@ -594,7 +619,7 @@ function checkDeadlineValidity(startTimestamp, durationDays) {
594
619
  throw Error('User decrypt request has expired');
595
620
  }
596
621
  }
597
- const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, options) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays) => {
622
+ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, instanceOptions) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays, options) => {
598
623
  const extraData = '0x00';
599
624
  let pubKey;
600
625
  let privKey;
@@ -653,7 +678,7 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
653
678
  publicKey: publicKeySanitized,
654
679
  extraData,
655
680
  };
656
- const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', `${relayerUrl}/v1/user-decrypt`, payloadForRequest, options);
681
+ const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', `${relayerUrl}/v1/user-decrypt`, payloadForRequest, instanceOptions ?? options);
657
682
  // assume the KMS Signers have the correct order
658
683
  let indexedKmsSigners = kmsSigners.map((signer, index) => {
659
684
  return TKMS.new_server_id_addr(index + 1, signer);
@@ -935,7 +960,7 @@ function isFhevmRelayerInputProofResponse(json) {
935
960
  return (response.signatures.every((s) => typeof s === 'string') &&
936
961
  response.handles.every((h) => typeof h === 'string'));
937
962
  }
938
- const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerUrl, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners) => (contractAddress, userAddress) => {
963
+ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerUrl, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners, instanceOptions) => (contractAddress, userAddress) => {
939
964
  if (!isAddress(contractAddress)) {
940
965
  throw new Error('Contract address is not a valid address.');
941
966
  }
@@ -998,7 +1023,7 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
998
1023
  contractChainId: ('0x' + chainId.toString(16)),
999
1024
  extraData,
1000
1025
  };
1001
- const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', `${relayerUrl}/v1/input-proof`, payload, options);
1026
+ const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', `${relayerUrl}/v1/input-proof`, payload, options ?? instanceOptions);
1002
1027
  if (!isFhevmRelayerInputProofResponse(json)) {
1003
1028
  throwRelayerInternalError('INPUT_PROOF', json);
1004
1029
  }
@@ -1120,7 +1145,7 @@ function deserializeDecryptedResult(handles, decryptedResult) {
1120
1145
  handles.forEach((handle, idx) => (results[handle] = rawValues[idx]));
1121
1146
  return results;
1122
1147
  }
1123
- const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, options) => async (_handles) => {
1148
+ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, instanceOptions) => async (_handles, options) => {
1124
1149
  const extraData = '0x00';
1125
1150
  const acl = new ethers.Contract(aclContractAddress, aclABI, provider);
1126
1151
  let handles;
@@ -1145,7 +1170,7 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
1145
1170
  ciphertextHandles: handles,
1146
1171
  extraData,
1147
1172
  };
1148
- const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', `${relayerUrl}/v1/public-decrypt`, payloadForRequest, options);
1173
+ const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', `${relayerUrl}/v1/public-decrypt`, payloadForRequest, options ?? instanceOptions);
1149
1174
  // verify signatures on decryption:
1150
1175
  const domain = {
1151
1176
  name: 'Decryption',
@@ -1165,9 +1190,10 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
1165
1190
  ? result.decrypted_value
1166
1191
  : `0x${result.decrypted_value}`;
1167
1192
  const signatures = result.signatures;
1193
+ const signedExtraData = '0x';
1168
1194
  const recoveredAddresses = signatures.map((signature) => {
1169
1195
  const sig = signature.startsWith('0x') ? signature : `0x${signature}`;
1170
- const recoveredAddress = ethers.verifyTypedData(domain, types, { ctHandles: handles, decryptedResult, extraData }, sig);
1196
+ const recoveredAddress = ethers.verifyTypedData(domain, types, { ctHandles: handles, decryptedResult, extraData: signedExtraData }, sig);
1171
1197
  return recoveredAddress;
1172
1198
  });
1173
1199
  const thresholdReached = isThresholdReached(kmsSigners, recoveredAddresses, thresholdSigners);
@@ -1308,7 +1334,7 @@ const SepoliaConfig = {
1308
1334
  relayerUrl: 'https://relayer.testnet.zama.cloud',
1309
1335
  };
1310
1336
  const createInstance = async (config) => {
1311
- const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, } = config;
1337
+ const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, auth, } = config;
1312
1338
  if (!kmsContractAddress || !isAddress(kmsContractAddress)) {
1313
1339
  throw new Error('KMS contract address is not valid or empty');
1314
1340
  }
@@ -1340,8 +1366,8 @@ const createInstance = async (config) => {
1340
1366
  createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, cleanURL(config.relayerUrl), publicKeyData.publicKey, publicParamsData, coprocessorSigners, thresholdCoprocessorSigners),
1341
1367
  generateKeypair,
1342
1368
  createEIP712: createEIP712(verifyingContractAddressDecryption, chainId),
1343
- publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
1344
- userDecrypt: userDecryptRequest(kmsSigners, gatewayChainId, chainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
1369
+ publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider, auth && { auth }),
1370
+ userDecrypt: userDecryptRequest(kmsSigners, gatewayChainId, chainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider, auth && { auth }),
1345
1371
  getPublicKey: () => publicKeyData.publicKey
1346
1372
  ? {
1347
1373
  publicKey: publicKeyData.publicKey.safe_serialize(SERIALIZED_SIZE_LIMIT_PK),
package/lib/web.d.ts CHANGED
@@ -2,6 +2,56 @@ import { Eip1193Provider } from 'ethers';
2
2
  import { InitInput as KMSInput } from 'tkms';
3
3
  import { InitInput as TFHEInput } from 'tfhe';
4
4
 
5
+ /**
6
+ * Custom cookie authentication
7
+ */
8
+ declare type ApiKeyCookie = {
9
+ __type: 'ApiKeyCookie';
10
+ /**
11
+ * The cookie name. The default value is `x-api-key`.
12
+ */
13
+ cookie?: string;
14
+ /**
15
+ * The API key.
16
+ */
17
+ value: string;
18
+ };
19
+
20
+ /**
21
+ * Custom header authentication
22
+ */
23
+ declare type ApiKeyHeader = {
24
+ __type: 'ApiKeyHeader';
25
+ /**
26
+ * The header name. The default value is `x-api-key`.
27
+ */
28
+ header?: string;
29
+ /**
30
+ * The API key.
31
+ */
32
+ value: string;
33
+ };
34
+
35
+ /**
36
+ * Set the authentication method for the request. The default is no authentication.
37
+ * It supports:
38
+ * - Bearer Token
39
+ * - Custom header
40
+ * - Custom cookie
41
+ */
42
+ declare type Auth = BearerToken | ApiKeyHeader | ApiKeyCookie;
43
+
44
+ /**
45
+ * Bearer Token Authentication
46
+ */
47
+ declare type BearerToken = {
48
+ __type: 'BearerToken';
49
+ /**
50
+ * The Bearer token.
51
+ */
52
+ token: string;
53
+ };
54
+
5
55
  /**
6
56
  * Creates an EIP712 structure specifically for user decrypt requests
7
57
  *
@@ -90,6 +140,7 @@ export declare type FhevmInstanceConfig = {
90
140
  data: Uint8Array | null;
91
141
  id: string | null;
92
142
  };
143
+ auth?: Auth;
93
144
  };
94
145
 
95
146
  export declare const generateKeypair: () => {
@@ -132,7 +183,7 @@ export declare type RelayerEncryptedInput = {
132
183
  addAddress: (value: string) => RelayerEncryptedInput;
133
184
  getBits: () => EncryptionTypes[];
134
185
  encrypt: (options?: {
135
- apiKey?: string;
186
+ auth?: Auth;
136
187
  }) => Promise<{
137
188
  handles: Uint8Array[];
138
189
  inputProof: Uint8Array;
package/lib/web.js CHANGED
@@ -16167,6 +16167,32 @@ const bytesToBigInt = function (byteArray) {
16167
16167
  return BigInt(`0x${hex}`);
16168
16168
  };
16169
16169
 
16170
+ function setAuth(init, auth) {
16171
+ if (auth) {
16172
+ switch (auth.__type) {
16173
+ case 'BearerToken':
16174
+ init.headers['Authorization'] =
16175
+ `Bearer ${auth.token}`;
16176
+ break;
16177
+ case 'ApiKeyHeader':
16178
+ init.headers[auth.header || 'x-api-key'] =
16179
+ auth.value;
16180
+ break;
16181
+ case 'ApiKeyCookie':
16182
+ if (typeof window !== 'undefined') {
16183
+ document.cookie = `${auth.cookie || 'x-api-key'}=${auth.value}; path=/; SameSite=Lax; Secure; HttpOnly;`;
16184
+ init.credentials = 'include';
16185
+ }
16186
+ else {
16187
+ let cookie = `${auth.cookie || 'x-api-key'}=${auth.value};`;
16188
+ init.headers['Cookie'] = cookie;
16189
+ }
16190
+ break;
16191
+ }
16192
+ }
16193
+ return init;
16194
+ }
16195
+
16170
16196
  function getErrorCause(e) {
16171
16197
  if (e instanceof Error && typeof e.cause === 'object' && e.cause !== null) {
16172
16198
  return e.cause;
@@ -16348,14 +16374,13 @@ function assertIsRelayerFetchResponseJson(json) {
16348
16374
  }
16349
16375
  }
16350
16376
  async function fetchRelayerJsonRpcPost(relayerOperation, url, payload, options) {
16351
- const init = {
16377
+ const init = setAuth({
16352
16378
  method: 'POST',
16353
16379
  headers: {
16354
16380
  'Content-Type': 'application/json',
16355
- ...(options?.apiKey && { 'x-api-key': options.apiKey }),
16356
16381
  },
16357
16382
  body: JSON.stringify(payload),
16358
- };
16383
+ }, options?.auth);
16359
16384
  let response;
16360
16385
  let json;
16361
16386
  try {
@@ -16725,7 +16750,7 @@ function checkDeadlineValidity(startTimestamp, durationDays) {
16725
16750
  throw Error('User decrypt request has expired');
16726
16751
  }
16727
16752
  }
16728
- const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, options) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays) => {
16753
+ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, instanceOptions) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays, options) => {
16729
16754
  const extraData = '0x00';
16730
16755
  let pubKey;
16731
16756
  let privKey;
@@ -16784,7 +16809,7 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
16784
16809
  publicKey: publicKeySanitized,
16785
16810
  extraData,
16786
16811
  };
16787
- const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', `${relayerUrl}/v1/user-decrypt`, payloadForRequest, options);
16812
+ const json = await fetchRelayerJsonRpcPost('USER_DECRYPT', `${relayerUrl}/v1/user-decrypt`, payloadForRequest, instanceOptions ?? options);
16788
16813
  // assume the KMS Signers have the correct order
16789
16814
  let indexedKmsSigners = kmsSigners.map((signer, index) => {
16790
16815
  return TKMS.new_server_id_addr(index + 1, signer);
@@ -17066,7 +17091,7 @@ function isFhevmRelayerInputProofResponse(json) {
17066
17091
  return (response.signatures.every((s) => typeof s === 'string') &&
17067
17092
  response.handles.every((h) => typeof h === 'string'));
17068
17093
  }
17069
- const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerUrl, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners) => (contractAddress, userAddress) => {
17094
+ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerUrl, tfheCompactPublicKey, publicParams, coprocessorSigners, thresholdCoprocessorSigners, instanceOptions) => (contractAddress, userAddress) => {
17070
17095
  if (!isAddress(contractAddress)) {
17071
17096
  throw new Error('Contract address is not a valid address.');
17072
17097
  }
@@ -17129,7 +17154,7 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
17129
17154
  contractChainId: ('0x' + chainId.toString(16)),
17130
17155
  extraData,
17131
17156
  };
17132
- const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', `${relayerUrl}/v1/input-proof`, payload, options);
17157
+ const json = await fetchRelayerJsonRpcPost('INPUT_PROOF', `${relayerUrl}/v1/input-proof`, payload, options ?? instanceOptions);
17133
17158
  if (!isFhevmRelayerInputProofResponse(json)) {
17134
17159
  throwRelayerInternalError('INPUT_PROOF', json);
17135
17160
  }
@@ -17251,7 +17276,7 @@ function deserializeDecryptedResult(handles, decryptedResult) {
17251
17276
  handles.forEach((handle, idx) => (results[handle] = rawValues[idx]));
17252
17277
  return results;
17253
17278
  }
17254
- const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, options) => async (_handles) => {
17279
+ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider, instanceOptions) => async (_handles, options) => {
17255
17280
  const extraData = '0x00';
17256
17281
  const acl = new ethers.Contract(aclContractAddress, aclABI, provider);
17257
17282
  let handles;
@@ -17276,7 +17301,7 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
17276
17301
  ciphertextHandles: handles,
17277
17302
  extraData,
17278
17303
  };
17279
- const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', `${relayerUrl}/v1/public-decrypt`, payloadForRequest, options);
17304
+ const json = await fetchRelayerJsonRpcPost('PUBLIC_DECRYPT', `${relayerUrl}/v1/public-decrypt`, payloadForRequest, options ?? instanceOptions);
17280
17305
  // verify signatures on decryption:
17281
17306
  const domain = {
17282
17307
  name: 'Decryption',
@@ -17296,9 +17321,10 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
17296
17321
  ? result.decrypted_value
17297
17322
  : `0x${result.decrypted_value}`;
17298
17323
  const signatures = result.signatures;
17324
+ const signedExtraData = '0x';
17299
17325
  const recoveredAddresses = signatures.map((signature) => {
17300
17326
  const sig = signature.startsWith('0x') ? signature : `0x${signature}`;
17301
- const recoveredAddress = ethers.verifyTypedData(domain, types, { ctHandles: handles, decryptedResult, extraData }, sig);
17327
+ const recoveredAddress = ethers.verifyTypedData(domain, types, { ctHandles: handles, decryptedResult, extraData: signedExtraData }, sig);
17302
17328
  return recoveredAddress;
17303
17329
  });
17304
17330
  const thresholdReached = isThresholdReached(kmsSigners, recoveredAddresses, thresholdSigners);
@@ -17439,7 +17465,7 @@ const SepoliaConfig = {
17439
17465
  relayerUrl: 'https://relayer.testnet.zama.cloud',
17440
17466
  };
17441
17467
  const createInstance = async (config) => {
17442
- const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, } = config;
17468
+ const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, auth, } = config;
17443
17469
  if (!kmsContractAddress || !isAddress(kmsContractAddress)) {
17444
17470
  throw new Error('KMS contract address is not valid or empty');
17445
17471
  }
@@ -17471,8 +17497,8 @@ const createInstance = async (config) => {
17471
17497
  createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, cleanURL(config.relayerUrl), publicKeyData.publicKey, publicParamsData, coprocessorSigners, thresholdCoprocessorSigners),
17472
17498
  generateKeypair,
17473
17499
  createEIP712: createEIP712(verifyingContractAddressDecryption, chainId),
17474
- publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
17475
- userDecrypt: userDecryptRequest(kmsSigners, gatewayChainId, chainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
17500
+ publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider, auth && { auth }),
17501
+ userDecrypt: userDecryptRequest(kmsSigners, gatewayChainId, chainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider, auth && { auth }),
17476
17502
  getPublicKey: () => publicKeyData.publicKey
17477
17503
  ? {
17478
17504
  publicKey: publicKeyData.publicKey.safe_serialize(SERIALIZED_SIZE_LIMIT_PK),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zama-fhe/relayer-sdk",
3
- "version": "0.2.0-5",
3
+ "version": "0.2.0",
4
4
  "description": "fhevm Relayer SDK",
5
5
  "main": "lib/node.js",
6
6
  "types": "lib/node.d.ts",
@@ -61,15 +61,15 @@
61
61
  "ethers": "^6.15.0",
62
62
  "fetch-retry": "^6.0.0",
63
63
  "keccak": "^3.0.4",
64
- "wasm-feature-detect": "^1.8.0",
65
64
  "node-tfhe": "1.3.0",
65
+ "node-tkms": "^0.11.0",
66
66
  "tfhe": "1.3.0",
67
- "node-tkms": "0.11.0-26",
68
- "tkms": "0.11.0-26"
67
+ "tkms": "^0.11.0",
68
+ "wasm-feature-detect": "^1.8.0"
69
69
  },
70
70
  "devDependencies": {
71
- "@fetch-mock/jest": "0.2.16",
72
71
  "@fetch-mock/core": "0.7.1",
72
+ "@fetch-mock/jest": "0.2.16",
73
73
  "@jest/globals": "30.0.4",
74
74
  "@microsoft/api-extractor": "7.52.8",
75
75
  "@rollup/plugin-alias": "5.1.1",
@@ -102,6 +102,6 @@
102
102
  "typescript": "5.8.3",
103
103
  "vite": "7.0.5",
104
104
  "vite-plugin-node-polyfills": "0.24.0",
105
- "vite-plugin-static-copy": "3.1.1"
105
+ "vite-plugin-static-copy": "^3.1.2"
106
106
  }
107
107
  }