@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.
- package/bundle/kms_lib_bg.wasm +0 -0
- package/bundle/relayer-sdk-js.js +2917 -2898
- package/bundle/relayer-sdk-js.umd.cjs +9 -9
- package/lib/kms_lib_bg.wasm +0 -0
- package/lib/node.cjs +39 -13
- package/lib/node.d.ts +52 -1
- package/lib/node.js +39 -13
- package/lib/web.d.ts +52 -1
- package/lib/web.js +39 -13
- package/package.json +6 -6
package/lib/kms_lib_bg.wasm
CHANGED
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
"
|
|
68
|
-
"
|
|
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.
|
|
105
|
+
"vite-plugin-static-copy": "^3.1.2"
|
|
106
106
|
}
|
|
107
107
|
}
|