@cofhe/sdk 0.6.0 → 0.7.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/CHANGELOG.md +49 -0
- package/acps/acp.ts +411 -0
- package/acps/index.ts +70 -0
- package/{permits → acps}/onchain-utils.ts +49 -24
- package/acps/sealing.ts +90 -0
- package/acps/signature.ts +89 -0
- package/acps/store.ts +172 -0
- package/acps/test/acp.test.ts +615 -0
- package/acps/test/localstorage.test.ts +105 -0
- package/acps/test/sealing.test.ts +77 -0
- package/acps/test/store.test.ts +88 -0
- package/acps/test/validation.test.ts +361 -0
- package/acps/test-utils.ts +32 -0
- package/acps/types.ts +252 -0
- package/acps/validation.ts +392 -0
- package/adapters/test/ethers5.test.ts +4 -1
- package/adapters/test/ethers6.test.ts +4 -1
- package/adapters/test/wagmi.test.ts +5 -2
- package/chains/chains/stagingCofhe.ts +21 -0
- package/chains/index.ts +3 -1
- package/chains/test/chains.test.ts +2 -1
- package/core/acps.ts +625 -0
- package/core/client.ts +136 -39
- package/core/clientTypes.ts +52 -41
- package/core/config.ts +66 -5
- package/core/debug.ts +72 -0
- package/core/decrypt/MockThresholdNetworkAbi.ts +20 -11
- package/core/decrypt/apiError.ts +104 -0
- package/core/decrypt/cofheMocksDecryptForTx.ts +11 -11
- package/core/decrypt/cofheMocksDecryptForView.ts +7 -7
- package/core/decrypt/decryptForTxBuilder.ts +102 -102
- package/core/decrypt/decryptForViewBuilder.ts +90 -90
- package/core/decrypt/submitRetry.ts +38 -30
- package/core/decrypt/tnDecryptV1.ts +5 -5
- package/core/decrypt/tnDecryptV2.ts +45 -34
- package/core/decrypt/tnSealOutputV1.ts +4 -3
- package/core/decrypt/tnSealOutputV2.ts +44 -31
- package/core/encrypt/cofheMocksZkVerifySign.ts +59 -74
- package/core/encrypt/encryptInputsBuilder.ts +86 -52
- package/core/encrypt/zkPackProveVerify.ts +25 -18
- package/core/error.ts +34 -6
- package/core/index.ts +14 -14
- package/core/test/acpDefaults.test.ts +52 -0
- package/core/test/acps.test.ts +596 -0
- package/core/test/apiError.test.ts +130 -0
- package/core/test/client.test.ts +22 -19
- package/core/test/config.test.ts +25 -5
- package/core/test/decrypt.test.ts +40 -35
- package/core/test/decryptBuilders.test.ts +68 -68
- package/core/test/decryptErrorCodes.test.ts +217 -0
- package/core/test/encryptInputsBuilder.test.ts +72 -41
- package/core/test/pollCallbacks.test.ts +89 -18
- package/core/test/stagingRedirect.ts +18 -0
- package/core/test/submitRetry.test.ts +182 -0
- package/core/types.ts +9 -69
- package/dist/acp-Wi6isVQI.d.cts +407 -0
- package/dist/acp-Wi6isVQI.d.ts +407 -0
- package/dist/acps.cjs +1081 -0
- package/dist/acps.d.cts +480 -0
- package/dist/acps.d.ts +480 -0
- package/dist/acps.js +2 -0
- package/dist/chains.cjs +14 -1
- package/dist/chains.d.cts +30 -1
- package/dist/chains.d.ts +30 -1
- package/dist/chains.js +1 -1
- package/dist/{chunk-PE5V5CCV.js → chunk-43USWPEH.js} +1000 -604
- package/dist/{chunk-MTRAXQXC.js → chunk-N6IDQRRU.js} +14 -2
- package/dist/chunk-Q7CBWGQX.js +1029 -0
- package/dist/{clientTypes-CyUvRRzA.d.ts → clientTypes-BN3nbzYM.d.ts} +342 -165
- package/dist/{clientTypes-BDy1qIBu.d.cts → clientTypes-CYZjFznO.d.cts} +342 -165
- package/dist/core.cjs +1431 -1026
- package/dist/core.d.cts +55 -10
- package/dist/core.d.ts +55 -10
- package/dist/core.js +3 -3
- package/dist/node.cjs +1356 -976
- package/dist/node.d.cts +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/node.js +3 -3
- package/dist/web.cjs +1356 -976
- package/dist/web.d.cts +2 -2
- package/dist/web.d.ts +2 -2
- package/dist/web.js +3 -3
- package/node/test/inherited.test.ts +75 -65
- package/node/test/tfheinit.test.ts +23 -8
- package/package.json +6 -6
- package/web/test/client.web.test.ts +5 -1
- package/web/test/inherited.web.test.ts +75 -65
- package/web/test/tfheinit.web.test.ts +14 -5
- package/web/test/worker.config.web.test.ts +38 -23
- package/web/test/worker.output.web.test.ts +25 -24
- package/core/encrypt/encryptUtils.ts +0 -67
- package/core/permits.ts +0 -206
- package/core/test/permits.test.ts +0 -534
- package/dist/chunk-VB62WYPL.js +0 -978
- package/dist/permit-DnVMDT5h.d.cts +0 -376
- package/dist/permit-DnVMDT5h.d.ts +0 -376
- package/dist/permits.cjs +0 -1026
- package/dist/permits.d.cts +0 -353
- package/dist/permits.d.ts +0 -353
- package/dist/permits.js +0 -2
- package/permits/index.ts +0 -68
- package/permits/permit.ts +0 -385
- package/permits/sealing.ts +0 -131
- package/permits/signature.ts +0 -79
- package/permits/store.ts +0 -157
- package/permits/test/localstorage.test.ts +0 -113
- package/permits/test/permit.test.ts +0 -557
- package/permits/test/sealing.test.ts +0 -84
- package/permits/test/store.test.ts +0 -88
- package/permits/test/validation.test.ts +0 -361
- package/permits/test-utils.ts +0 -28
- package/permits/types.ts +0 -204
- package/permits/validation.ts +0 -327
- /package/{permits → acps}/utils.ts +0 -0
package/dist/core.cjs
CHANGED
|
@@ -16,58 +16,78 @@ var nacl__default = /*#__PURE__*/_interopDefault(nacl);
|
|
|
16
16
|
// core/client.ts
|
|
17
17
|
|
|
18
18
|
// core/error.ts
|
|
19
|
-
var CofheErrorCode = /* @__PURE__ */ ((
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
19
|
+
var CofheErrorCode = /* @__PURE__ */ ((CofheErrorCode2) => {
|
|
20
|
+
CofheErrorCode2["InternalError"] = "INTERNAL_ERROR";
|
|
21
|
+
CofheErrorCode2["UnknownEnvironment"] = "UNKNOWN_ENVIRONMENT";
|
|
22
|
+
CofheErrorCode2["InitTfheFailed"] = "INIT_TFHE_FAILED";
|
|
23
|
+
CofheErrorCode2["InitViemFailed"] = "INIT_VIEM_FAILED";
|
|
24
|
+
CofheErrorCode2["InitEthersFailed"] = "INIT_ETHERS_FAILED";
|
|
25
|
+
CofheErrorCode2["NotConnected"] = "NOT_CONNECTED";
|
|
26
|
+
CofheErrorCode2["MissingPublicClient"] = "MISSING_PUBLIC_CLIENT";
|
|
27
|
+
CofheErrorCode2["MissingWalletClient"] = "MISSING_WALLET_CLIENT";
|
|
28
|
+
CofheErrorCode2["MissingProviderParam"] = "MISSING_PROVIDER_PARAM";
|
|
29
|
+
CofheErrorCode2["EmptySecurityZonesParam"] = "EMPTY_SECURITY_ZONES_PARAM";
|
|
30
|
+
CofheErrorCode2["InvalidACPData"] = "INVALID_ACP_DATA";
|
|
31
|
+
CofheErrorCode2["InvalidACPDomain"] = "INVALID_ACP_DOMAIN";
|
|
32
|
+
CofheErrorCode2["ACPNotFound"] = "ACP_NOT_FOUND";
|
|
33
|
+
CofheErrorCode2["CannotRemoveLastACP"] = "CANNOT_REMOVE_LAST_ACP";
|
|
34
|
+
CofheErrorCode2["AccountUninitialized"] = "ACCOUNT_UNINITIALIZED";
|
|
35
|
+
CofheErrorCode2["ChainIdUninitialized"] = "CHAIN_ID_UNINITIALIZED";
|
|
36
|
+
CofheErrorCode2["ConsumingContractUninitialized"] = "CONSUMING_CONTRACT_UNINITIALIZED";
|
|
37
|
+
CofheErrorCode2["SealOutputFailed"] = "SEAL_OUTPUT_FAILED";
|
|
38
|
+
CofheErrorCode2["SealOutputReturnedNull"] = "SEAL_OUTPUT_RETURNED_NULL";
|
|
39
|
+
CofheErrorCode2["InvalidUtype"] = "INVALID_UTYPE";
|
|
40
|
+
CofheErrorCode2["DecryptFailed"] = "DECRYPT_FAILED";
|
|
41
|
+
CofheErrorCode2["DecryptReturnedNull"] = "DECRYPT_RETURNED_NULL";
|
|
42
|
+
CofheErrorCode2["ZkMocksInsertCtHashesFailed"] = "ZK_MOCKS_INSERT_CT_HASHES_FAILED";
|
|
43
|
+
CofheErrorCode2["ZkMocksCalcCtHashesFailed"] = "ZK_MOCKS_CALC_CT_HASHES_FAILED";
|
|
44
|
+
CofheErrorCode2["ZkMocksVerifySignFailed"] = "ZK_MOCKS_VERIFY_SIGN_FAILED";
|
|
45
|
+
CofheErrorCode2["ZkMocksCreateProofSignatureFailed"] = "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED";
|
|
46
|
+
CofheErrorCode2["ZkVerifyFailed"] = "ZK_VERIFY_FAILED";
|
|
47
|
+
CofheErrorCode2["ZkPackFailed"] = "ZK_PACK_FAILED";
|
|
48
|
+
CofheErrorCode2["ZkProveFailed"] = "ZK_PROVE_FAILED";
|
|
49
|
+
CofheErrorCode2["EncryptRemainingInItems"] = "ENCRYPT_REMAINING_IN_ITEMS";
|
|
50
|
+
CofheErrorCode2["ZkUninitialized"] = "ZK_UNINITIALIZED";
|
|
51
|
+
CofheErrorCode2["ZkVerifierUrlUninitialized"] = "ZK_VERIFIER_URL_UNINITIALIZED";
|
|
52
|
+
CofheErrorCode2["ThresholdNetworkUrlUninitialized"] = "THRESHOLD_NETWORK_URL_UNINITIALIZED";
|
|
53
|
+
CofheErrorCode2["MissingConfig"] = "MISSING_CONFIG";
|
|
54
|
+
CofheErrorCode2["UnsupportedChain"] = "UNSUPPORTED_CHAIN";
|
|
55
|
+
CofheErrorCode2["MissingZkBuilderAndCrsGenerator"] = "MISSING_ZK_BUILDER_AND_CRS_GENERATOR";
|
|
56
|
+
CofheErrorCode2["MissingTfhePublicKeyDeserializer"] = "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER";
|
|
57
|
+
CofheErrorCode2["MissingCompactPkeCrsDeserializer"] = "MISSING_COMPACT_PKE_CRS_DESERIALIZER";
|
|
58
|
+
CofheErrorCode2["MissingFheKey"] = "MISSING_FHE_KEY";
|
|
59
|
+
CofheErrorCode2["MissingCrs"] = "MISSING_CRS";
|
|
60
|
+
CofheErrorCode2["FetchKeysFailed"] = "FETCH_KEYS_FAILED";
|
|
61
|
+
CofheErrorCode2["PublicWalletGetChainIdFailed"] = "PUBLIC_WALLET_GET_CHAIN_ID_FAILED";
|
|
62
|
+
CofheErrorCode2["PublicWalletGetAddressesFailed"] = "PUBLIC_WALLET_GET_ADDRESSES_FAILED";
|
|
63
|
+
CofheErrorCode2["RehydrateKeysStoreFailed"] = "REHYDRATE_KEYS_STORE_FAILED";
|
|
64
|
+
CofheErrorCode2["BadRequest"] = "BAD_REQUEST";
|
|
65
|
+
CofheErrorCode2["UnknownChain"] = "UNKNOWN_CHAIN";
|
|
66
|
+
CofheErrorCode2["ACPMalformed"] = "ACP_MALFORMED";
|
|
67
|
+
CofheErrorCode2["ACPDenied"] = "ACP_DENIED";
|
|
68
|
+
CofheErrorCode2["ACPExpired"] = "ACP_EXPIRED";
|
|
69
|
+
CofheErrorCode2["ACPInvalid"] = "ACP_INVALID";
|
|
70
|
+
CofheErrorCode2["ACPRevoked"] = "ACP_REVOKED";
|
|
71
|
+
CofheErrorCode2["NotPubliclyAllowed"] = "NOT_PUBLICLY_ALLOWED";
|
|
72
|
+
CofheErrorCode2["CtNotFound"] = "CT_NOT_FOUND";
|
|
73
|
+
CofheErrorCode2["UnsupportedSecurityZone"] = "UNSUPPORTED_SECURITY_ZONE";
|
|
74
|
+
CofheErrorCode2["UnsupportedType"] = "UNSUPPORTED_TYPE";
|
|
75
|
+
CofheErrorCode2["SigningFailed"] = "SIGNING_FAILED";
|
|
76
|
+
CofheErrorCode2["CtSourceError"] = "CT_SOURCE_ERROR";
|
|
77
|
+
CofheErrorCode2["ACPVerifierError"] = "ACP_VERIFIER_ERROR";
|
|
78
|
+
CofheErrorCode2["CtSourceTimeout"] = "CT_SOURCE_TIMEOUT";
|
|
79
|
+
CofheErrorCode2["ACPVerifierTimeout"] = "ACP_VERIFIER_TIMEOUT";
|
|
80
|
+
CofheErrorCode2["ACPRequired"] = "ACP_REQUIRED";
|
|
81
|
+
CofheErrorCode2["SealFailed"] = "SEAL_FAILED";
|
|
82
|
+
return CofheErrorCode2;
|
|
64
83
|
})(CofheErrorCode || {});
|
|
65
84
|
var CofheError = class _CofheError extends Error {
|
|
66
85
|
code;
|
|
67
86
|
cause;
|
|
68
87
|
hint;
|
|
69
88
|
context;
|
|
70
|
-
|
|
89
|
+
apiErrorCode;
|
|
90
|
+
constructor({ code, message, cause, hint, context, apiErrorCode }) {
|
|
71
91
|
const fullMessage = cause ? `${message} | Caused by: ${cause.message}` : message;
|
|
72
92
|
super(fullMessage);
|
|
73
93
|
this.name = "CofheError";
|
|
@@ -75,6 +95,7 @@ var CofheError = class _CofheError extends Error {
|
|
|
75
95
|
this.cause = cause;
|
|
76
96
|
this.hint = hint;
|
|
77
97
|
this.context = context;
|
|
98
|
+
this.apiErrorCode = apiErrorCode;
|
|
78
99
|
if (Error.captureStackTrace) {
|
|
79
100
|
Error.captureStackTrace(this, _CofheError);
|
|
80
101
|
}
|
|
@@ -93,6 +114,7 @@ var CofheError = class _CofheError extends Error {
|
|
|
93
114
|
message: wrapperError?.message ?? "An internal error occurred",
|
|
94
115
|
hint: wrapperError?.hint,
|
|
95
116
|
context: wrapperError?.context,
|
|
117
|
+
apiErrorCode: wrapperError?.apiErrorCode,
|
|
96
118
|
cause
|
|
97
119
|
});
|
|
98
120
|
}
|
|
@@ -106,6 +128,7 @@ var CofheError = class _CofheError extends Error {
|
|
|
106
128
|
message: this.message,
|
|
107
129
|
hint: this.hint,
|
|
108
130
|
context: this.context,
|
|
131
|
+
apiErrorCode: this.apiErrorCode,
|
|
109
132
|
cause: this.cause ? {
|
|
110
133
|
name: this.cause.name,
|
|
111
134
|
message: this.cause.message,
|
|
@@ -118,7 +141,8 @@ var CofheError = class _CofheError extends Error {
|
|
|
118
141
|
* Returns a human-readable string representation of the error
|
|
119
142
|
*/
|
|
120
143
|
toString() {
|
|
121
|
-
const
|
|
144
|
+
const codeSuffix = this.apiErrorCode ? ` (api: ${this.apiErrorCode})` : "";
|
|
145
|
+
const parts = [`${this.name} [${this.code}]${codeSuffix}: ${this.message}`];
|
|
122
146
|
if (this.hint) {
|
|
123
147
|
parts.push(`Hint: ${this.hint}`);
|
|
124
148
|
}
|
|
@@ -215,10 +239,6 @@ var FheAllUTypes = [
|
|
|
215
239
|
// FheTypes.Uint256,
|
|
216
240
|
7 /* Uint160 */
|
|
217
241
|
];
|
|
218
|
-
function assertCorrectEncryptedItemInput(input) {
|
|
219
|
-
if (!input.signature.startsWith("0x"))
|
|
220
|
-
throw new Error("Signature must be a hex string starting with 0x");
|
|
221
|
-
}
|
|
222
242
|
var EncryptableFactoriesImpl = {
|
|
223
243
|
bool: (data, securityZone = 0) => ({ data, securityZone, utype: 0 /* Bool */ }),
|
|
224
244
|
address: (data, securityZone = 0) => ({ data, securityZone, utype: 7 /* Uint160 */ }),
|
|
@@ -498,18 +518,19 @@ var constructZkPoKMetadata = (accountAddr, securityZone, chainId) => {
|
|
|
498
518
|
metadata.set(chainIdBytes, 1 + accountBytes.length);
|
|
499
519
|
return metadata;
|
|
500
520
|
};
|
|
501
|
-
var
|
|
521
|
+
var zkVerifyBatch = async (verifierUrl, serializedBytes, address, securityZone, chainId, consumingContract) => {
|
|
502
522
|
const packed_list = toHexString(serializedBytes);
|
|
503
523
|
const sz_byte = new Uint8Array([securityZone]);
|
|
504
524
|
const payload = {
|
|
505
525
|
packed_list,
|
|
506
526
|
account_addr: address,
|
|
507
527
|
security_zone: sz_byte[0],
|
|
508
|
-
chain_id: chainId
|
|
528
|
+
chain_id: chainId,
|
|
529
|
+
contract_address: consumingContract
|
|
509
530
|
};
|
|
510
531
|
const body = JSON.stringify(payload);
|
|
511
532
|
try {
|
|
512
|
-
const response = await fetch(`${verifierUrl}/
|
|
533
|
+
const response = await fetch(`${verifierUrl}/verifyBatch`, {
|
|
513
534
|
method: "POST",
|
|
514
535
|
headers: {
|
|
515
536
|
"Content-Type": "application/json"
|
|
@@ -520,26 +541,25 @@ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chain
|
|
|
520
541
|
const errorBody = await response.text();
|
|
521
542
|
throw new CofheError({
|
|
522
543
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
523
|
-
message: `HTTP error! ZK proof verification failed - ${errorBody}`
|
|
544
|
+
message: `HTTP error! ZK batch proof verification failed - ${errorBody}`
|
|
524
545
|
});
|
|
525
546
|
}
|
|
526
547
|
const json = await response.json();
|
|
527
548
|
if (json.status !== "success") {
|
|
528
549
|
throw new CofheError({
|
|
529
550
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
530
|
-
message: `ZK proof verification response malformed - ${json.error}`
|
|
551
|
+
message: `ZK batch proof verification response malformed - ${json.error}`
|
|
531
552
|
});
|
|
532
553
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
});
|
|
554
|
+
const { ciphertexts, signature, recid } = json.data;
|
|
555
|
+
return {
|
|
556
|
+
outputs: ciphertexts,
|
|
557
|
+
signature: concatSigRecid(signature, recid)
|
|
558
|
+
};
|
|
539
559
|
} catch (e) {
|
|
540
560
|
throw new CofheError({
|
|
541
561
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
542
|
-
message: `ZK proof verification failed`,
|
|
562
|
+
message: `ZK batch proof verification failed`,
|
|
543
563
|
cause: e instanceof Error ? e : void 0
|
|
544
564
|
});
|
|
545
565
|
}
|
|
@@ -784,67 +804,59 @@ async function insertCtHashes(items, walletClient) {
|
|
|
784
804
|
});
|
|
785
805
|
}
|
|
786
806
|
}
|
|
787
|
-
async function
|
|
788
|
-
let signatures = [];
|
|
789
|
-
let encInputSignerClient;
|
|
807
|
+
async function createBatchProofSignature(items, securityZone, account, consumingContract) {
|
|
790
808
|
try {
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
809
|
+
const itemHashes = items.map(
|
|
810
|
+
(item) => viem.keccak256(
|
|
811
|
+
viem.encodePacked(
|
|
812
|
+
["uint256", "uint8", "uint8", "address", "uint256", "address"],
|
|
813
|
+
[
|
|
814
|
+
BigInt(item.ctHash),
|
|
815
|
+
item.utype,
|
|
816
|
+
securityZone,
|
|
817
|
+
account,
|
|
818
|
+
BigInt(chains.hardhat.id),
|
|
819
|
+
consumingContract
|
|
820
|
+
]
|
|
821
|
+
)
|
|
822
|
+
)
|
|
823
|
+
);
|
|
824
|
+
const batchDigest = viem.keccak256(
|
|
825
|
+
viem.encodePacked(
|
|
826
|
+
itemHashes.map(() => "bytes32"),
|
|
827
|
+
itemHashes
|
|
828
|
+
)
|
|
829
|
+
);
|
|
830
|
+
return await accounts.sign({
|
|
831
|
+
hash: batchDigest,
|
|
832
|
+
privateKey: MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
|
|
833
|
+
to: "hex"
|
|
800
834
|
});
|
|
801
|
-
}
|
|
802
|
-
try {
|
|
803
|
-
for (const item of items) {
|
|
804
|
-
const packedData = viem.encodePacked(
|
|
805
|
-
["uint256", "uint8", "uint8", "address", "uint256"],
|
|
806
|
-
[BigInt(item.ctHash), item.utype, securityZone, account, BigInt(chains.hardhat.id)]
|
|
807
|
-
);
|
|
808
|
-
const messageHash = viem.keccak256(packedData);
|
|
809
|
-
const signature = await accounts.sign({
|
|
810
|
-
hash: messageHash,
|
|
811
|
-
privateKey: MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
|
|
812
|
-
to: "hex"
|
|
813
|
-
});
|
|
814
|
-
signatures.push(signature);
|
|
815
|
-
}
|
|
816
835
|
} catch (err) {
|
|
817
836
|
throw new CofheError({
|
|
818
837
|
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
819
|
-
message: `mockZkVerifySign
|
|
838
|
+
message: `mockZkVerifySign createBatchProofSignature failed while signing the batch digest`,
|
|
820
839
|
cause: err instanceof Error ? err : void 0,
|
|
821
840
|
context: {
|
|
822
841
|
items,
|
|
823
|
-
securityZone
|
|
824
|
-
|
|
825
|
-
});
|
|
826
|
-
}
|
|
827
|
-
if (signatures.length !== items.length) {
|
|
828
|
-
throw new CofheError({
|
|
829
|
-
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
830
|
-
message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
|
|
831
|
-
context: {
|
|
832
|
-
items,
|
|
833
|
-
securityZone
|
|
842
|
+
securityZone,
|
|
843
|
+
consumingContract
|
|
834
844
|
}
|
|
835
845
|
});
|
|
836
846
|
}
|
|
837
|
-
return signatures;
|
|
838
847
|
}
|
|
839
|
-
async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
|
|
848
|
+
async function cofheMocksZkVerifySign(items, account, securityZone, consumingContract, publicClient, walletClient, zkvWalletClient) {
|
|
840
849
|
const _walletClient = zkvWalletClient ?? createMockZkVerifierSigner();
|
|
841
850
|
const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
|
|
842
851
|
await insertCtHashes(encryptableItems, _walletClient);
|
|
843
|
-
const
|
|
844
|
-
return
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
852
|
+
const signature = await createBatchProofSignature(encryptableItems, securityZone, account, consumingContract);
|
|
853
|
+
return {
|
|
854
|
+
outputs: encryptableItems.map((item) => ({
|
|
855
|
+
ct_hash: item.ctHash.toString(),
|
|
856
|
+
ct_type: item.utype
|
|
857
|
+
})),
|
|
858
|
+
signature
|
|
859
|
+
};
|
|
848
860
|
}
|
|
849
861
|
var EnvironmentSchema = zod.z.enum(["MOCK", "TESTNET", "MAINNET"]);
|
|
850
862
|
var CofheChainSchema = zod.z.object({
|
|
@@ -887,8 +899,8 @@ var CofheConfigSchema = zod.z.object({
|
|
|
887
899
|
environment: zod.z.enum(["node", "hardhat", "web", "react"]).optional().default("node"),
|
|
888
900
|
/** List of supported chain configurations */
|
|
889
901
|
supportedChains: zod.z.array(zod.z.custom()),
|
|
890
|
-
/** Default
|
|
891
|
-
|
|
902
|
+
/** Default acp expiration in seconds, default is 30 days */
|
|
903
|
+
defaultACPExpiration: zod.z.number().optional().default(60 * 60 * 24 * 30),
|
|
892
904
|
/** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
|
|
893
905
|
fheKeyStorage: zod.z.object({
|
|
894
906
|
getItem: zod.z.custom((val) => typeof val === "function", {
|
|
@@ -903,6 +915,12 @@ var CofheConfigSchema = zod.z.object({
|
|
|
903
915
|
}).or(zod.z.null()).default(null),
|
|
904
916
|
/** Whether to use Web Workers for ZK proof generation (web platform only) */
|
|
905
917
|
useWorkers: zod.z.boolean().optional().default(true),
|
|
918
|
+
/** ACP acp defaults */
|
|
919
|
+
acp: zod.z.object({
|
|
920
|
+
defaultRevoker: zod.z.custom().optional(),
|
|
921
|
+
defaultContractScopes: zod.z.custom().optional(),
|
|
922
|
+
sharingRegistry: zod.z.custom().optional()
|
|
923
|
+
}).optional().default({}),
|
|
906
924
|
/** Mocks configs */
|
|
907
925
|
mocks: zod.z.object({
|
|
908
926
|
decryptDelay: zod.z.number().optional().default(0),
|
|
@@ -913,8 +931,19 @@ var CofheConfigSchema = zod.z.object({
|
|
|
913
931
|
zkvWalletClient: zod.z.any().optional()
|
|
914
932
|
}).optional()
|
|
915
933
|
});
|
|
934
|
+
var RENAMED_COFHE_CONFIG_KEYS = {
|
|
935
|
+
defaultPermitExpiration: "defaultACPExpiration"
|
|
936
|
+
};
|
|
937
|
+
function assertNoRenamedConfigKeys(config, renamedKeys, label) {
|
|
938
|
+
const stale = Object.keys(config).filter((key) => key in renamedKeys);
|
|
939
|
+
if (stale.length === 0)
|
|
940
|
+
return;
|
|
941
|
+
const renames = stale.map((key) => `\`${key}\` is now \`${renamedKeys[key]}\``).join("; ");
|
|
942
|
+
throw new Error(`Invalid ${label}: ${renames}. See the v0.7.0 migration guide.`);
|
|
943
|
+
}
|
|
916
944
|
function createCofheConfigBase(config) {
|
|
917
|
-
|
|
945
|
+
assertNoRenamedConfigKeys(config, RENAMED_COFHE_CONFIG_KEYS, "cofhe configuration");
|
|
946
|
+
const result = CofheConfigSchema.strict().safeParse(config);
|
|
918
947
|
if (!result.success) {
|
|
919
948
|
throw new Error(`Invalid cofhe configuration: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
|
|
920
949
|
}
|
|
@@ -1266,9 +1295,9 @@ var BaseBuilder = class {
|
|
|
1266
1295
|
// core/encrypt/encryptInputsBuilder.ts
|
|
1267
1296
|
var EncryptInputsBuilder = class extends BaseBuilder {
|
|
1268
1297
|
securityZone;
|
|
1298
|
+
consumingContract;
|
|
1269
1299
|
stepCallback;
|
|
1270
1300
|
inputItems;
|
|
1271
|
-
hpp = false;
|
|
1272
1301
|
zkvWalletClient;
|
|
1273
1302
|
tfhePublicKeyDeserializer;
|
|
1274
1303
|
compactPkeCrsDeserializer;
|
|
@@ -1335,20 +1364,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1335
1364
|
this.keysStorage = params.keysStorage;
|
|
1336
1365
|
this.useWorker = params.config?.useWorkers ?? true;
|
|
1337
1366
|
}
|
|
1338
|
-
/**
|
|
1339
|
-
* @param account - Account that will create the tx using the encrypted inputs.
|
|
1340
|
-
*
|
|
1341
|
-
* If not provided, the account will be fetched from the connected walletClient.
|
|
1342
|
-
*
|
|
1343
|
-
* Example:
|
|
1344
|
-
* ```typescript
|
|
1345
|
-
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1346
|
-
* .setAccount("0x123")
|
|
1347
|
-
* .execute();
|
|
1348
|
-
* ```
|
|
1349
|
-
*
|
|
1350
|
-
* @returns The chainable EncryptInputsBuilder instance.
|
|
1351
|
-
*/
|
|
1352
1367
|
setAccount(account) {
|
|
1353
1368
|
this.account = account;
|
|
1354
1369
|
return this;
|
|
@@ -1356,20 +1371,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1356
1371
|
getAccount() {
|
|
1357
1372
|
return this.account;
|
|
1358
1373
|
}
|
|
1359
|
-
/**
|
|
1360
|
-
* @param chainId - Chain that will consume the encrypted inputs.
|
|
1361
|
-
*
|
|
1362
|
-
* If not provided, the chainId will be fetched from the connected publicClient.
|
|
1363
|
-
*
|
|
1364
|
-
* Example:
|
|
1365
|
-
* ```typescript
|
|
1366
|
-
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1367
|
-
* .setChainId(11155111)
|
|
1368
|
-
* .execute();
|
|
1369
|
-
* ```
|
|
1370
|
-
*
|
|
1371
|
-
* @returns The chainable EncryptInputsBuilder instance.
|
|
1372
|
-
*/
|
|
1373
1374
|
setChainId(chainId) {
|
|
1374
1375
|
this.chainId = chainId;
|
|
1375
1376
|
return this;
|
|
@@ -1377,20 +1378,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1377
1378
|
getChainId() {
|
|
1378
1379
|
return this.chainId;
|
|
1379
1380
|
}
|
|
1380
|
-
/**
|
|
1381
|
-
* @param securityZone - Security zone to encrypt the inputs for.
|
|
1382
|
-
*
|
|
1383
|
-
* If not provided, the default securityZone 0 will be used.
|
|
1384
|
-
*
|
|
1385
|
-
* Example:
|
|
1386
|
-
* ```typescript
|
|
1387
|
-
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1388
|
-
* .setSecurityZone(1)
|
|
1389
|
-
* .execute();
|
|
1390
|
-
* ```
|
|
1391
|
-
*
|
|
1392
|
-
* @returns The chainable EncryptInputsBuilder instance.
|
|
1393
|
-
*/
|
|
1394
1381
|
setSecurityZone(securityZone) {
|
|
1395
1382
|
this.securityZone = securityZone;
|
|
1396
1383
|
return this;
|
|
@@ -1399,33 +1386,44 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1399
1386
|
return this.securityZone;
|
|
1400
1387
|
}
|
|
1401
1388
|
/**
|
|
1389
|
+
* @param address - The contract that will consume the resulting hashes+signature (i.e. the
|
|
1390
|
+
* contract that will call `FHE.asEuint*`/`FHE.asEuint*s` with them).
|
|
1391
|
+
*
|
|
1392
|
+
* Required before `execute()` - the verifier binds this address into the signed digest, so a
|
|
1393
|
+
* batch signed for one contract cannot be replayed into another.
|
|
1394
|
+
*
|
|
1402
1395
|
* Example:
|
|
1403
1396
|
* ```typescript
|
|
1404
1397
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1405
|
-
* .
|
|
1398
|
+
* .setConsumingContract("0x123...890")
|
|
1406
1399
|
* .execute();
|
|
1407
1400
|
* ```
|
|
1408
1401
|
*
|
|
1409
|
-
* @returns
|
|
1402
|
+
* @returns The chainable EncryptInputsBuilder instance.
|
|
1410
1403
|
*/
|
|
1411
|
-
|
|
1412
|
-
this.
|
|
1404
|
+
setConsumingContract(address) {
|
|
1405
|
+
this.consumingContract = address;
|
|
1413
1406
|
return this;
|
|
1414
1407
|
}
|
|
1408
|
+
getConsumingContract() {
|
|
1409
|
+
return this.consumingContract;
|
|
1410
|
+
}
|
|
1415
1411
|
/**
|
|
1416
|
-
*
|
|
1417
|
-
*
|
|
1418
|
-
* Overrides the config-level useWorkers setting for this specific encryption.
|
|
1419
|
-
*
|
|
1420
|
-
* Example:
|
|
1421
|
-
* ```typescript
|
|
1422
|
-
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1423
|
-
* .setUseWorker(false)
|
|
1424
|
-
* .execute();
|
|
1425
|
-
* ```
|
|
1426
|
-
*
|
|
1427
|
-
* @returns The chainable EncryptInputsBuilder instance.
|
|
1412
|
+
* Asserts that this.consumingContract is populated
|
|
1413
|
+
* @throws {CofheError} If consumingContract is not set
|
|
1428
1414
|
*/
|
|
1415
|
+
assertConsumingContract() {
|
|
1416
|
+
if (this.consumingContract)
|
|
1417
|
+
return;
|
|
1418
|
+
throw new CofheError({
|
|
1419
|
+
code: "CONSUMING_CONTRACT_UNINITIALIZED" /* ConsumingContractUninitialized */,
|
|
1420
|
+
message: "Consuming contract is not set",
|
|
1421
|
+
hint: "Use setConsumingContract(...) to set the contract that will consume the encrypted inputs.",
|
|
1422
|
+
context: {
|
|
1423
|
+
consumingContract: this.consumingContract
|
|
1424
|
+
}
|
|
1425
|
+
});
|
|
1426
|
+
}
|
|
1429
1427
|
setUseWorker(useWorker) {
|
|
1430
1428
|
this.useWorker = useWorker;
|
|
1431
1429
|
return this;
|
|
@@ -1446,21 +1444,6 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1446
1444
|
getUseWorker() {
|
|
1447
1445
|
return this.useWorker;
|
|
1448
1446
|
}
|
|
1449
|
-
/**
|
|
1450
|
-
* @param callback - Function to be called with the encryption step.
|
|
1451
|
-
*
|
|
1452
|
-
* Useful for debugging and tracking the progress of the encryption process.
|
|
1453
|
-
* Useful for a UI element that shows the progress of the encryption process.
|
|
1454
|
-
*
|
|
1455
|
-
* Example:
|
|
1456
|
-
* ```typescript
|
|
1457
|
-
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1458
|
-
* .onStep((step: EncryptStep) => console.log(step))
|
|
1459
|
-
* .execute();
|
|
1460
|
-
* ```
|
|
1461
|
-
*
|
|
1462
|
-
* @returns The EncryptInputsBuilder instance.
|
|
1463
|
-
*/
|
|
1464
1447
|
onStep(callback) {
|
|
1465
1448
|
this.stepCallback = callback;
|
|
1466
1449
|
return this;
|
|
@@ -1599,6 +1582,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1599
1582
|
this.assertAccount();
|
|
1600
1583
|
this.assertPublicClient();
|
|
1601
1584
|
this.assertWalletClient();
|
|
1585
|
+
this.assertConsumingContract();
|
|
1602
1586
|
const [initTfheDelay, fetchKeysDelay, packDelay, proveDelay, verifyDelay] = this.resolveEncryptDelays();
|
|
1603
1587
|
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
1604
1588
|
await sleep(initTfheDelay);
|
|
@@ -1624,22 +1608,17 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1624
1608
|
this.fireStepEnd("prove" /* Prove */, { isMocks: true, mockSleep: proveDelay });
|
|
1625
1609
|
this.fireStepStart("verify" /* Verify */);
|
|
1626
1610
|
await sleep(verifyDelay);
|
|
1627
|
-
const
|
|
1611
|
+
const result = await cofheMocksZkVerifySign(
|
|
1628
1612
|
this.inputItems,
|
|
1629
1613
|
this.account,
|
|
1630
1614
|
this.securityZone,
|
|
1615
|
+
this.consumingContract,
|
|
1631
1616
|
this.publicClient,
|
|
1632
1617
|
this.walletClient,
|
|
1633
1618
|
this.zkvWalletClient
|
|
1634
1619
|
);
|
|
1635
|
-
const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
|
|
1636
|
-
ctHash: BigInt(ct_hash),
|
|
1637
|
-
securityZone: this.securityZone,
|
|
1638
|
-
utype: this.inputItems[index].utype,
|
|
1639
|
-
signature
|
|
1640
|
-
}));
|
|
1641
1620
|
this.fireStepEnd("verify" /* Verify */, { isMocks: true, mockSleep: verifyDelay });
|
|
1642
|
-
return
|
|
1621
|
+
return result;
|
|
1643
1622
|
}
|
|
1644
1623
|
/**
|
|
1645
1624
|
* In the production context, perform a true encryption with the CoFHE coprocessor.
|
|
@@ -1647,6 +1626,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1647
1626
|
async productionExecute() {
|
|
1648
1627
|
this.assertAccount();
|
|
1649
1628
|
this.assertChainId();
|
|
1629
|
+
this.assertConsumingContract();
|
|
1650
1630
|
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
1651
1631
|
const tfheInitializationExecuted = await this.initTfheOrThrow();
|
|
1652
1632
|
this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
|
|
@@ -1681,26 +1661,24 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1681
1661
|
});
|
|
1682
1662
|
this.fireStepStart("verify" /* Verify */);
|
|
1683
1663
|
const zkVerifierUrl = await this.getZkVerifierUrl();
|
|
1684
|
-
const
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
})
|
|
1664
|
+
const result = await zkVerifyBatch(
|
|
1665
|
+
zkVerifierUrl,
|
|
1666
|
+
proof,
|
|
1667
|
+
this.account,
|
|
1668
|
+
this.securityZone,
|
|
1669
|
+
this.chainId,
|
|
1670
|
+
this.consumingContract
|
|
1692
1671
|
);
|
|
1693
1672
|
this.fireStepEnd("verify" /* Verify */);
|
|
1694
|
-
return
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
return [...hashes, proof];
|
|
1673
|
+
return result;
|
|
1674
|
+
}
|
|
1675
|
+
/**
|
|
1676
|
+
* Converts a batch-verified result (per-item ctHash/ctType + one shared signature) into the
|
|
1677
|
+
* tuple returned by `execute()`: per-item hashes in input order, followed by the single signature.
|
|
1678
|
+
*/
|
|
1679
|
+
buildBatchResult(result) {
|
|
1680
|
+
const hashes = result.outputs.map((output) => "0x" + BigInt(output.ct_hash).toString(16).padStart(64, "0"));
|
|
1681
|
+
return [...hashes, result.signature];
|
|
1704
1682
|
}
|
|
1705
1683
|
/**
|
|
1706
1684
|
* Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
|
|
@@ -1722,18 +1700,16 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1722
1700
|
* @returns The encrypted inputs.
|
|
1723
1701
|
*/
|
|
1724
1702
|
async execute() {
|
|
1725
|
-
let
|
|
1703
|
+
let result;
|
|
1726
1704
|
if (this.chainId === chains.hardhat.id)
|
|
1727
|
-
|
|
1705
|
+
result = await this.mocksExecute();
|
|
1728
1706
|
else
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
return this.structsToHashPlusProof(items);
|
|
1732
|
-
return items;
|
|
1707
|
+
result = await this.productionExecute();
|
|
1708
|
+
return this.buildBatchResult(result);
|
|
1733
1709
|
}
|
|
1734
1710
|
};
|
|
1735
1711
|
|
|
1736
|
-
//
|
|
1712
|
+
// acps/utils.ts
|
|
1737
1713
|
var fromHexString = (hexString) => {
|
|
1738
1714
|
const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
|
|
1739
1715
|
const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
|
|
@@ -1753,120 +1729,33 @@ function toBigInt(value) {
|
|
|
1753
1729
|
return value;
|
|
1754
1730
|
}
|
|
1755
1731
|
}
|
|
1756
|
-
function toBeArray(value) {
|
|
1757
|
-
const bigIntValue = typeof value === "number" ? BigInt(value) : value;
|
|
1758
|
-
const hex = bigIntValue.toString(16);
|
|
1759
|
-
const paddedHex = hex.length % 2 === 0 ? hex : "0" + hex;
|
|
1760
|
-
return fromHexString(paddedHex);
|
|
1761
|
-
}
|
|
1762
|
-
function isString(value) {
|
|
1763
|
-
if (typeof value !== "string") {
|
|
1764
|
-
throw new Error(`Expected value which is \`string\`, received value of type \`${typeof value}\`.`);
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
function isNumber(value) {
|
|
1768
|
-
const is = typeof value === "number" && !Number.isNaN(value);
|
|
1769
|
-
if (!is) {
|
|
1770
|
-
throw new Error(`Expected value which is \`number\`, received value of type \`${typeof value}\`.`);
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
function isBigIntOrNumber(value) {
|
|
1774
|
-
const is = typeof value === "bigint";
|
|
1775
|
-
if (!is) {
|
|
1776
|
-
try {
|
|
1777
|
-
isNumber(value);
|
|
1778
|
-
} catch (e) {
|
|
1779
|
-
throw new Error(`Value ${value} is not a number or bigint: ${typeof value}`);
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
}
|
|
1783
1732
|
|
|
1784
|
-
//
|
|
1785
|
-
var
|
|
1786
|
-
var PUBLIC_KEY_LENGTH = 64;
|
|
1787
|
-
var SealingKey = class _SealingKey {
|
|
1788
|
-
/**
|
|
1789
|
-
* The private key used for decryption.
|
|
1790
|
-
*/
|
|
1791
|
-
privateKey;
|
|
1792
|
-
/**
|
|
1793
|
-
* The public key used for encryption.
|
|
1794
|
-
*/
|
|
1795
|
-
publicKey;
|
|
1796
|
-
/**
|
|
1797
|
-
* Constructs a SealingKey instance with the given private and public keys.
|
|
1798
|
-
*
|
|
1799
|
-
* @param {string} privateKey - The private key used for decryption.
|
|
1800
|
-
* @param {string} publicKey - The public key used for encryption.
|
|
1801
|
-
* @throws Will throw an error if the provided keys lengths do not match
|
|
1802
|
-
* the required lengths for private and public keys.
|
|
1803
|
-
*/
|
|
1804
|
-
constructor(privateKey, publicKey) {
|
|
1805
|
-
if (privateKey.length !== PRIVATE_KEY_LENGTH) {
|
|
1806
|
-
throw new Error(`Private key must be of length ${PRIVATE_KEY_LENGTH}`);
|
|
1807
|
-
}
|
|
1808
|
-
if (publicKey.length !== PUBLIC_KEY_LENGTH) {
|
|
1809
|
-
throw new Error(`Public key must be of length ${PUBLIC_KEY_LENGTH}`);
|
|
1810
|
-
}
|
|
1811
|
-
this.privateKey = privateKey;
|
|
1812
|
-
this.publicKey = publicKey;
|
|
1813
|
-
}
|
|
1814
|
-
unseal = (parsedData) => {
|
|
1815
|
-
const nonce = parsedData.nonce instanceof Uint8Array ? parsedData.nonce : new Uint8Array(parsedData.nonce);
|
|
1816
|
-
const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
|
|
1817
|
-
const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
|
|
1818
|
-
const privateKeyBytes = fromHexString(this.privateKey);
|
|
1819
|
-
const decryptedMessage = nacl__default.default.box.open(dataToDecrypt, nonce, ephemPublicKey, privateKeyBytes);
|
|
1820
|
-
if (!decryptedMessage) {
|
|
1821
|
-
throw new Error("Failed to decrypt message");
|
|
1822
|
-
}
|
|
1823
|
-
return toBigInt(decryptedMessage);
|
|
1824
|
-
};
|
|
1825
|
-
/**
|
|
1826
|
-
* Serializes the SealingKey to a JSON object.
|
|
1827
|
-
*/
|
|
1828
|
-
serialize = () => {
|
|
1829
|
-
return {
|
|
1830
|
-
privateKey: this.privateKey,
|
|
1831
|
-
publicKey: this.publicKey
|
|
1832
|
-
};
|
|
1833
|
-
};
|
|
1834
|
-
/**
|
|
1835
|
-
* Deserializes the SealingKey from a JSON object.
|
|
1836
|
-
*/
|
|
1837
|
-
static deserialize = (privateKey, publicKey) => {
|
|
1838
|
-
return new _SealingKey(privateKey, publicKey);
|
|
1839
|
-
};
|
|
1840
|
-
/**
|
|
1841
|
-
* Seals (encrypts) the provided message for a receiver with the specified public key.
|
|
1842
|
-
*
|
|
1843
|
-
* @param {bigint | number} value - The message to be encrypted.
|
|
1844
|
-
* @param {string} publicKey - The public key of the intended recipient.
|
|
1845
|
-
* @returns string - The encrypted message in hexadecimal format.
|
|
1846
|
-
* @static
|
|
1847
|
-
* @throws Will throw if the provided publicKey or value do not meet defined preconditions.
|
|
1848
|
-
*/
|
|
1849
|
-
static seal = (value, publicKey) => {
|
|
1850
|
-
isString(publicKey);
|
|
1851
|
-
isBigIntOrNumber(value);
|
|
1852
|
-
const ephemeralKeyPair = nacl__default.default.box.keyPair();
|
|
1853
|
-
const nonce = nacl__default.default.randomBytes(nacl__default.default.box.nonceLength);
|
|
1854
|
-
const encryptedMessage = nacl__default.default.box(toBeArray(value), nonce, fromHexString(publicKey), ephemeralKeyPair.secretKey);
|
|
1855
|
-
return {
|
|
1856
|
-
data: encryptedMessage,
|
|
1857
|
-
public_key: ephemeralKeyPair.publicKey,
|
|
1858
|
-
nonce
|
|
1859
|
-
};
|
|
1860
|
-
};
|
|
1861
|
-
};
|
|
1733
|
+
// acps/sealing.ts
|
|
1734
|
+
var KEY_HEX_LENGTH = 64;
|
|
1862
1735
|
var GenerateSealingKey = () => {
|
|
1863
1736
|
const sodiumKeypair = nacl__default.default.box.keyPair();
|
|
1864
|
-
return
|
|
1737
|
+
return {
|
|
1738
|
+
privateKey: `0x${toHexString2(sodiumKeypair.secretKey)}`,
|
|
1739
|
+
publicKey: `0x${toHexString2(sodiumKeypair.publicKey)}`
|
|
1740
|
+
};
|
|
1741
|
+
};
|
|
1742
|
+
var unsealWithPrivateKey = (privateKey, parsedData) => {
|
|
1743
|
+
assertKeyLength(privateKey, "Private");
|
|
1744
|
+
const nonce = parsedData.nonce instanceof Uint8Array ? parsedData.nonce : new Uint8Array(parsedData.nonce);
|
|
1745
|
+
const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
|
|
1746
|
+
const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
|
|
1747
|
+
const decryptedMessage = nacl__default.default.box.open(dataToDecrypt, nonce, ephemPublicKey, fromHexString(privateKey));
|
|
1748
|
+
if (!decryptedMessage) {
|
|
1749
|
+
throw new Error("Failed to decrypt message");
|
|
1750
|
+
}
|
|
1751
|
+
return toBigInt(decryptedMessage);
|
|
1752
|
+
};
|
|
1753
|
+
var assertKeyLength = (key, kind) => {
|
|
1754
|
+
const bare = key.startsWith("0x") ? key.slice(2) : key;
|
|
1755
|
+
if (bare.length !== KEY_HEX_LENGTH) {
|
|
1756
|
+
throw new Error(`${kind} key must be of length ${KEY_HEX_LENGTH}`);
|
|
1757
|
+
}
|
|
1865
1758
|
};
|
|
1866
|
-
var SerializedSealingPair = zod.z.object({
|
|
1867
|
-
privateKey: zod.z.string(),
|
|
1868
|
-
publicKey: zod.z.string()
|
|
1869
|
-
});
|
|
1870
1759
|
var addressSchema = zod.z.string().refine((val) => viem.isAddress(val), {
|
|
1871
1760
|
error: "Invalid address"
|
|
1872
1761
|
}).transform((val) => viem.getAddress(val));
|
|
@@ -1885,46 +1774,70 @@ var bytesNotEmptySchema = bytesSchema.refine((val) => val !== "0x", {
|
|
|
1885
1774
|
error: "Must not be empty"
|
|
1886
1775
|
});
|
|
1887
1776
|
var DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1e3) + 7 * 24 * 60 * 60;
|
|
1888
|
-
var
|
|
1889
|
-
|
|
1777
|
+
var handlesSchema = zod.z.array(zod.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "Invalid handle: expected 32-byte hex")).optional().default([]);
|
|
1778
|
+
var contractsSchema = zod.z.array(addressSchema).optional().default([]);
|
|
1779
|
+
var SCOPE_GLOBAL = 0;
|
|
1780
|
+
var SCOPE_CONTRACT = 1;
|
|
1781
|
+
var SCOPE_HANDLES = 2;
|
|
1782
|
+
var ScopeConsistencyRefinement = [
|
|
1783
|
+
(data) => data.scope === SCOPE_GLOBAL && data.contracts.length === 0 && data.handles.length === 0 || data.scope === SCOPE_CONTRACT && data.contracts.length > 0 && data.handles.length === 0 || data.scope === SCOPE_HANDLES && data.handles.length > 0 && data.contracts.length === 0,
|
|
1784
|
+
{
|
|
1785
|
+
error: "ACP scope :: arrays must match the scope mode (Global: both empty; Contract: contracts only; Handles: handles only)",
|
|
1786
|
+
path: ["scope"]
|
|
1787
|
+
}
|
|
1788
|
+
];
|
|
1789
|
+
var withDerivedScope = (data) => ({
|
|
1790
|
+
...data,
|
|
1791
|
+
scope: data.scope ?? (data.contracts.length > 0 ? SCOPE_CONTRACT : data.handles.length > 0 ? SCOPE_HANDLES : SCOPE_GLOBAL)
|
|
1792
|
+
});
|
|
1793
|
+
var zACPWithDefaults = zod.z.object({
|
|
1794
|
+
name: zod.z.string().optional().default("Unnamed ACP"),
|
|
1890
1795
|
type: zod.z.enum(["self", "sharing", "recipient"]),
|
|
1891
1796
|
issuer: addressNotZeroSchema,
|
|
1892
1797
|
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1893
1798
|
recipient: addressSchema.optional().default(viem.zeroAddress),
|
|
1894
|
-
|
|
1895
|
-
|
|
1799
|
+
revokerData: zod.z.int().optional().default(0),
|
|
1800
|
+
revokerContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1801
|
+
scope: zod.z.int().min(0).max(2).optional().default(0),
|
|
1802
|
+
contracts: contractsSchema,
|
|
1803
|
+
handles: handlesSchema,
|
|
1896
1804
|
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1897
1805
|
recipientSignature: bytesSchema.optional().default("0x")
|
|
1898
1806
|
});
|
|
1899
|
-
var
|
|
1900
|
-
|
|
1807
|
+
var zACPWithSealingKeys = zACPWithDefaults.extend({
|
|
1808
|
+
/** X25519 private key, 0x-prefixed 32-byte hex; never leaves the client */
|
|
1809
|
+
sealingPrivateKey: zod.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "Invalid sealing private key").optional(),
|
|
1810
|
+
sealingKey: zod.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "Invalid sealing key").optional()
|
|
1901
1811
|
});
|
|
1902
1812
|
var ExternalValidatorRefinement = [
|
|
1903
|
-
(data) => data.
|
|
1813
|
+
(data) => data.revokerData !== 0 && data.revokerContract !== viem.zeroAddress || data.revokerData === 0 && data.revokerContract === viem.zeroAddress,
|
|
1904
1814
|
{
|
|
1905
|
-
error: "
|
|
1906
|
-
path: ["
|
|
1815
|
+
error: "ACP external revoker :: revokerData and revokerContract must either both be set or both be unset.",
|
|
1816
|
+
path: ["revokerData", "revokerContract"]
|
|
1907
1817
|
}
|
|
1908
1818
|
];
|
|
1909
1819
|
var RecipientRefinement = [
|
|
1910
1820
|
(data) => data.issuer !== data.recipient,
|
|
1911
1821
|
{
|
|
1912
|
-
error: "Sharing
|
|
1822
|
+
error: "Sharing acp :: issuer and recipient must not be the same",
|
|
1913
1823
|
path: ["issuer", "recipient"]
|
|
1914
1824
|
}
|
|
1915
1825
|
];
|
|
1916
|
-
var
|
|
1826
|
+
var SelfACPOptionsValidator = zod.z.object({
|
|
1917
1827
|
type: zod.z.literal("self").optional().default("self"),
|
|
1918
1828
|
issuer: addressNotZeroSchema,
|
|
1919
|
-
name: zod.z.string().optional().default("Unnamed
|
|
1829
|
+
name: zod.z.string().optional().default("Unnamed ACP"),
|
|
1920
1830
|
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1921
1831
|
recipient: addressSchema.optional().default(viem.zeroAddress),
|
|
1922
|
-
|
|
1923
|
-
|
|
1832
|
+
revokerData: zod.z.int().optional().default(0),
|
|
1833
|
+
revokerContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1834
|
+
scope: zod.z.int().min(0).max(2).optional(),
|
|
1835
|
+
contracts: contractsSchema,
|
|
1836
|
+
handles: handlesSchema,
|
|
1924
1837
|
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1925
1838
|
recipientSignature: bytesSchema.optional().default("0x")
|
|
1926
|
-
}).refine(...ExternalValidatorRefinement);
|
|
1927
|
-
var
|
|
1839
|
+
}).refine(...ExternalValidatorRefinement).transform(withDerivedScope).refine(...ScopeConsistencyRefinement);
|
|
1840
|
+
var SelfACPValidator = zACPWithSealingKeys.refine((data) => data.type === "self", {
|
|
1928
1841
|
error: "Type must be 'self'"
|
|
1929
1842
|
}).refine((data) => data.recipient === viem.zeroAddress, {
|
|
1930
1843
|
error: "Recipient must be zeroAddress"
|
|
@@ -1933,18 +1846,21 @@ var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type ===
|
|
|
1933
1846
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
1934
1847
|
error: "RecipientSignature must be empty"
|
|
1935
1848
|
}).refine(...ExternalValidatorRefinement);
|
|
1936
|
-
var
|
|
1849
|
+
var SharingACPOptionsValidator = zod.z.object({
|
|
1937
1850
|
type: zod.z.literal("sharing").optional().default("sharing"),
|
|
1938
1851
|
issuer: addressNotZeroSchema,
|
|
1939
1852
|
recipient: addressNotZeroSchema,
|
|
1940
|
-
name: zod.z.string().optional().default("Unnamed
|
|
1853
|
+
name: zod.z.string().optional().default("Unnamed ACP"),
|
|
1941
1854
|
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1942
|
-
|
|
1943
|
-
|
|
1855
|
+
revokerData: zod.z.int().optional().default(0),
|
|
1856
|
+
revokerContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1857
|
+
scope: zod.z.int().min(0).max(2).optional(),
|
|
1858
|
+
contracts: contractsSchema,
|
|
1859
|
+
handles: handlesSchema,
|
|
1944
1860
|
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1945
1861
|
recipientSignature: bytesSchema.optional().default("0x")
|
|
1946
|
-
}).refine(...RecipientRefinement).refine(...ExternalValidatorRefinement);
|
|
1947
|
-
var
|
|
1862
|
+
}).refine(...RecipientRefinement).refine(...ExternalValidatorRefinement).transform(withDerivedScope).refine(...ScopeConsistencyRefinement);
|
|
1863
|
+
var SharingACPValidator = zACPWithSealingKeys.refine((data) => data.type === "sharing", {
|
|
1948
1864
|
error: "Type must be 'sharing'"
|
|
1949
1865
|
}).refine((data) => data.recipient !== viem.zeroAddress, {
|
|
1950
1866
|
error: "Recipient must not be zeroAddress"
|
|
@@ -1953,18 +1869,21 @@ var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type =
|
|
|
1953
1869
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
1954
1870
|
error: "RecipientSignature must be empty"
|
|
1955
1871
|
}).refine(...ExternalValidatorRefinement);
|
|
1956
|
-
var
|
|
1872
|
+
var ImportACPOptionsValidator = zod.z.object({
|
|
1957
1873
|
type: zod.z.literal("recipient").optional().default("recipient"),
|
|
1958
1874
|
issuer: addressNotZeroSchema,
|
|
1959
1875
|
recipient: addressNotZeroSchema,
|
|
1960
|
-
name: zod.z.string().optional().default("Unnamed
|
|
1876
|
+
name: zod.z.string().optional().default("Unnamed ACP"),
|
|
1961
1877
|
expiration: zod.z.int(),
|
|
1962
|
-
|
|
1963
|
-
|
|
1878
|
+
revokerData: zod.z.int().optional().default(0),
|
|
1879
|
+
revokerContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1880
|
+
scope: zod.z.int().min(0).max(2).optional(),
|
|
1881
|
+
contracts: contractsSchema,
|
|
1882
|
+
handles: handlesSchema,
|
|
1964
1883
|
issuerSignature: bytesNotEmptySchema,
|
|
1965
1884
|
recipientSignature: bytesSchema.optional().default("0x")
|
|
1966
|
-
}).refine(...ExternalValidatorRefinement);
|
|
1967
|
-
var
|
|
1885
|
+
}).refine(...ExternalValidatorRefinement).transform(withDerivedScope).refine(...ScopeConsistencyRefinement);
|
|
1886
|
+
var ImportACPValidator = zACPWithSealingKeys.refine((data) => data.type === "recipient", {
|
|
1968
1887
|
error: "Type must be 'recipient'"
|
|
1969
1888
|
}).refine((data) => data.recipient !== viem.zeroAddress, {
|
|
1970
1889
|
error: "Recipient must not be zeroAddress"
|
|
@@ -1980,116 +1899,125 @@ var safeParseAndThrowFormatted = (schema, data, message) => {
|
|
|
1980
1899
|
}
|
|
1981
1900
|
return result.data;
|
|
1982
1901
|
};
|
|
1983
|
-
var
|
|
1984
|
-
return safeParseAndThrowFormatted(
|
|
1902
|
+
var validateSelfACPOptions = (options) => {
|
|
1903
|
+
return safeParseAndThrowFormatted(SelfACPOptionsValidator, options, "Invalid self acp options");
|
|
1985
1904
|
};
|
|
1986
|
-
var
|
|
1987
|
-
return safeParseAndThrowFormatted(
|
|
1905
|
+
var validateSharingACPOptions = (options) => {
|
|
1906
|
+
return safeParseAndThrowFormatted(SharingACPOptionsValidator, options, "Invalid sharing acp options");
|
|
1988
1907
|
};
|
|
1989
|
-
var
|
|
1990
|
-
return safeParseAndThrowFormatted(
|
|
1908
|
+
var validateImportACPOptions = (options) => {
|
|
1909
|
+
return safeParseAndThrowFormatted(ImportACPOptionsValidator, options, "Invalid import acp options");
|
|
1991
1910
|
};
|
|
1992
|
-
var
|
|
1993
|
-
return safeParseAndThrowFormatted(
|
|
1911
|
+
var validateSelfACP = (acp) => {
|
|
1912
|
+
return safeParseAndThrowFormatted(SelfACPValidator, acp, "Invalid self acp");
|
|
1994
1913
|
};
|
|
1995
|
-
var
|
|
1996
|
-
return safeParseAndThrowFormatted(
|
|
1914
|
+
var validateSharingACP = (acp) => {
|
|
1915
|
+
return safeParseAndThrowFormatted(SharingACPValidator, acp, "Invalid sharing acp");
|
|
1997
1916
|
};
|
|
1998
|
-
var
|
|
1999
|
-
return safeParseAndThrowFormatted(
|
|
1917
|
+
var validateImportACP = (acp) => {
|
|
1918
|
+
return safeParseAndThrowFormatted(ImportACPValidator, acp, "Invalid import acp");
|
|
2000
1919
|
};
|
|
2001
1920
|
var ValidationUtils = {
|
|
2002
1921
|
/**
|
|
2003
|
-
* Check if
|
|
1922
|
+
* Check if acp is expired
|
|
2004
1923
|
*/
|
|
2005
|
-
isExpired: (
|
|
2006
|
-
return
|
|
1924
|
+
isExpired: (acp) => {
|
|
1925
|
+
return acp.expiration < Math.floor(Date.now() / 1e3);
|
|
2007
1926
|
},
|
|
2008
1927
|
/**
|
|
2009
|
-
* Check if
|
|
1928
|
+
* Check if acp is signed by the active party
|
|
2010
1929
|
*/
|
|
2011
|
-
isSigned: (
|
|
2012
|
-
if (
|
|
2013
|
-
return
|
|
1930
|
+
isSigned: (acp) => {
|
|
1931
|
+
if (acp.type === "self" || acp.type === "sharing") {
|
|
1932
|
+
return acp.issuerSignature !== "0x";
|
|
2014
1933
|
}
|
|
2015
|
-
if (
|
|
2016
|
-
return
|
|
1934
|
+
if (acp.type === "recipient") {
|
|
1935
|
+
return acp.recipientSignature !== "0x";
|
|
2017
1936
|
}
|
|
2018
1937
|
return false;
|
|
2019
1938
|
},
|
|
2020
1939
|
/**
|
|
2021
|
-
* Checks that
|
|
1940
|
+
* Checks that an ACP is signed and not expired.
|
|
2022
1941
|
*/
|
|
2023
|
-
isSignedAndNotExpired: (
|
|
2024
|
-
if (ValidationUtils.isExpired(
|
|
1942
|
+
isSignedAndNotExpired: (acp) => {
|
|
1943
|
+
if (ValidationUtils.isExpired(acp)) {
|
|
2025
1944
|
return { valid: false, error: "expired" };
|
|
2026
1945
|
}
|
|
2027
|
-
if (!ValidationUtils.isSigned(
|
|
1946
|
+
if (!ValidationUtils.isSigned(acp)) {
|
|
2028
1947
|
return { valid: false, error: "not-signed" };
|
|
2029
1948
|
}
|
|
2030
1949
|
return { valid: true, error: null };
|
|
2031
1950
|
},
|
|
2032
1951
|
/**
|
|
2033
|
-
* Asserts that
|
|
1952
|
+
* Asserts that an ACP is signed and not expired.
|
|
2034
1953
|
*
|
|
2035
1954
|
* Throws `Error` with message:
|
|
2036
|
-
* - `
|
|
2037
|
-
* - `
|
|
1955
|
+
* - `ACP is expired`
|
|
1956
|
+
* - `ACP is not signed`
|
|
2038
1957
|
*/
|
|
2039
|
-
assertSignedAndNotExpired: (
|
|
2040
|
-
const result = ValidationUtils.isSignedAndNotExpired(
|
|
1958
|
+
assertSignedAndNotExpired: (acp) => {
|
|
1959
|
+
const result = ValidationUtils.isSignedAndNotExpired(acp);
|
|
2041
1960
|
if (result.valid)
|
|
2042
1961
|
return;
|
|
2043
1962
|
if (result.error === "expired") {
|
|
2044
|
-
throw new Error("
|
|
1963
|
+
throw new Error("ACP is expired");
|
|
2045
1964
|
}
|
|
2046
1965
|
if (result.error === "not-signed") {
|
|
2047
|
-
throw new Error("
|
|
1966
|
+
throw new Error("ACP is not signed");
|
|
2048
1967
|
}
|
|
2049
|
-
throw new Error("
|
|
1968
|
+
throw new Error("ACP is invalid");
|
|
2050
1969
|
},
|
|
2051
|
-
isValid: (
|
|
2052
|
-
const schema =
|
|
1970
|
+
isValid: (acp) => {
|
|
1971
|
+
const schema = acp.type === "self" ? SelfACPValidator : acp.type === "sharing" ? SharingACPValidator : acp.type === "recipient" ? ImportACPValidator : null;
|
|
2053
1972
|
if (schema == null)
|
|
2054
1973
|
return { valid: false, error: "invalid-schema" };
|
|
2055
|
-
const schemaResult = schema.safeParse(
|
|
1974
|
+
const schemaResult = schema.safeParse(acp);
|
|
2056
1975
|
if (!schemaResult.success)
|
|
2057
1976
|
return { valid: false, error: "invalid-schema" };
|
|
2058
|
-
return ValidationUtils.isSignedAndNotExpired(
|
|
1977
|
+
return ValidationUtils.isSignedAndNotExpired(acp);
|
|
2059
1978
|
}
|
|
2060
1979
|
};
|
|
2061
1980
|
|
|
2062
|
-
//
|
|
2063
|
-
var
|
|
1981
|
+
// acps/signature.ts
|
|
1982
|
+
var ACPSignatureAllFields = [
|
|
2064
1983
|
{ name: "issuer", type: "address" },
|
|
2065
1984
|
{ name: "expiration", type: "uint64" },
|
|
2066
1985
|
{ name: "recipient", type: "address" },
|
|
2067
|
-
{ name: "
|
|
2068
|
-
{ name: "
|
|
1986
|
+
{ name: "revokerData", type: "uint256" },
|
|
1987
|
+
{ name: "revokerContract", type: "address" },
|
|
1988
|
+
{ name: "scope", type: "uint8" },
|
|
1989
|
+
{ name: "contracts", type: "address[]" },
|
|
1990
|
+
{ name: "handles", type: "bytes32[]" },
|
|
2069
1991
|
{ name: "sealingKey", type: "bytes32" },
|
|
2070
1992
|
{ name: "issuerSignature", type: "bytes" }
|
|
2071
1993
|
];
|
|
2072
1994
|
var SignatureTypes = {
|
|
2073
|
-
|
|
1995
|
+
ACPIssuerSelf: [
|
|
2074
1996
|
"issuer",
|
|
2075
1997
|
"expiration",
|
|
2076
1998
|
"recipient",
|
|
2077
|
-
"
|
|
2078
|
-
"
|
|
1999
|
+
"revokerData",
|
|
2000
|
+
"revokerContract",
|
|
2001
|
+
"scope",
|
|
2002
|
+
"contracts",
|
|
2003
|
+
"handles",
|
|
2079
2004
|
"sealingKey"
|
|
2080
2005
|
],
|
|
2081
|
-
|
|
2006
|
+
ACPIssuerShared: [
|
|
2082
2007
|
"issuer",
|
|
2083
2008
|
"expiration",
|
|
2084
2009
|
"recipient",
|
|
2085
|
-
"
|
|
2086
|
-
"
|
|
2010
|
+
"revokerData",
|
|
2011
|
+
"revokerContract",
|
|
2012
|
+
"scope",
|
|
2013
|
+
"contracts",
|
|
2014
|
+
"handles"
|
|
2087
2015
|
],
|
|
2088
|
-
|
|
2016
|
+
ACPRecipient: ["sealingKey", "issuerSignature"]
|
|
2089
2017
|
};
|
|
2090
2018
|
var getSignatureTypesAndMessage = (primaryType, fields, values) => {
|
|
2091
2019
|
const types = {
|
|
2092
|
-
[primaryType]:
|
|
2020
|
+
[primaryType]: ACPSignatureAllFields.filter((fieldType) => fields.includes(fieldType.name))
|
|
2093
2021
|
};
|
|
2094
2022
|
const message = {};
|
|
2095
2023
|
fields.forEach((field) => {
|
|
@@ -2101,22 +2029,22 @@ var getSignatureTypesAndMessage = (primaryType, fields, values) => {
|
|
|
2101
2029
|
};
|
|
2102
2030
|
var SignatureUtils = {
|
|
2103
2031
|
/**
|
|
2104
|
-
* Get signature parameters for
|
|
2032
|
+
* Get signature parameters for an ACP
|
|
2105
2033
|
*/
|
|
2106
|
-
getSignatureParams: (
|
|
2107
|
-
return getSignatureTypesAndMessage(primaryType, SignatureTypes[primaryType],
|
|
2034
|
+
getSignatureParams: (acp, primaryType) => {
|
|
2035
|
+
return getSignatureTypesAndMessage(primaryType, SignatureTypes[primaryType], acp);
|
|
2108
2036
|
},
|
|
2109
2037
|
/**
|
|
2110
|
-
* Determine the required signature type based on
|
|
2038
|
+
* Determine the required signature type based on acp type
|
|
2111
2039
|
*/
|
|
2112
|
-
getPrimaryType: (
|
|
2113
|
-
if (
|
|
2114
|
-
return "
|
|
2115
|
-
if (
|
|
2116
|
-
return "
|
|
2117
|
-
if (
|
|
2118
|
-
return "
|
|
2119
|
-
throw new Error(`Unknown
|
|
2040
|
+
getPrimaryType: (acpType) => {
|
|
2041
|
+
if (acpType === "self")
|
|
2042
|
+
return "ACPIssuerSelf";
|
|
2043
|
+
if (acpType === "sharing")
|
|
2044
|
+
return "ACPIssuerShared";
|
|
2045
|
+
if (acpType === "recipient")
|
|
2046
|
+
return "ACPRecipient";
|
|
2047
|
+
throw new Error(`Unknown acp type: ${acpType}`);
|
|
2120
2048
|
}
|
|
2121
2049
|
};
|
|
2122
2050
|
var getAclAddress = async (publicClient) => {
|
|
@@ -2138,6 +2066,11 @@ var getAclEIP712Domain = async (publicClient) => {
|
|
|
2138
2066
|
functionName: "eip712Domain"
|
|
2139
2067
|
});
|
|
2140
2068
|
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
2069
|
+
if (version !== "2") {
|
|
2070
|
+
throw new Error(
|
|
2071
|
+
`Chain ${chainId}'s ACL serves EIP-712 domain version "${version}" \u2014 this SDK requires the upgraded (ACP-era) ACL, which signs as version "2". Pre-upgrade (V2 Permission) chains are not supported.`
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
2141
2074
|
return {
|
|
2142
2075
|
name,
|
|
2143
2076
|
version,
|
|
@@ -2145,23 +2078,26 @@ var getAclEIP712Domain = async (publicClient) => {
|
|
|
2145
2078
|
verifyingContract
|
|
2146
2079
|
};
|
|
2147
2080
|
};
|
|
2148
|
-
var
|
|
2081
|
+
var checkACPValidityOnChain = async (acp, publicClient) => {
|
|
2149
2082
|
const aclAddress = await getAclAddress(publicClient);
|
|
2150
2083
|
try {
|
|
2151
2084
|
await publicClient.simulateContract({
|
|
2152
2085
|
address: aclAddress,
|
|
2153
|
-
abi:
|
|
2154
|
-
functionName: "
|
|
2086
|
+
abi: checkACPValidityAbi,
|
|
2087
|
+
functionName: "checkPermissionValidity",
|
|
2155
2088
|
args: [
|
|
2156
2089
|
{
|
|
2157
|
-
issuer:
|
|
2158
|
-
expiration: BigInt(
|
|
2159
|
-
recipient:
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2090
|
+
issuer: acp.issuer,
|
|
2091
|
+
expiration: BigInt(acp.expiration),
|
|
2092
|
+
recipient: acp.recipient,
|
|
2093
|
+
revokerData: BigInt(acp.revokerData),
|
|
2094
|
+
revokerContract: acp.revokerContract,
|
|
2095
|
+
scope: acp.scope,
|
|
2096
|
+
contracts: acp.contracts,
|
|
2097
|
+
handles: acp.handles,
|
|
2098
|
+
sealingKey: acp.sealingKey,
|
|
2099
|
+
issuerSignature: acp.issuerSignature,
|
|
2100
|
+
recipientSignature: acp.recipientSignature
|
|
2165
2101
|
}
|
|
2166
2102
|
]
|
|
2167
2103
|
});
|
|
@@ -2174,14 +2110,14 @@ var checkPermitValidityOnChain = async (permission, publicClient) => {
|
|
|
2174
2110
|
throw new Error(errorName);
|
|
2175
2111
|
}
|
|
2176
2112
|
}
|
|
2177
|
-
const customErrorName = extractCustomErrorFromDetails(err,
|
|
2113
|
+
const customErrorName = extractCustomErrorFromDetails(err, checkACPValidityAbi);
|
|
2178
2114
|
if (customErrorName) {
|
|
2179
2115
|
throw new Error(customErrorName);
|
|
2180
2116
|
}
|
|
2181
2117
|
const hhDetailsData = extractReturnData(err);
|
|
2182
2118
|
if (hhDetailsData != null) {
|
|
2183
2119
|
const decoded = viem.decodeErrorResult({
|
|
2184
|
-
abi:
|
|
2120
|
+
abi: checkACPValidityAbi,
|
|
2185
2121
|
data: hhDetailsData
|
|
2186
2122
|
});
|
|
2187
2123
|
throw new Error(decoded.errorName);
|
|
@@ -2209,15 +2145,15 @@ function extractReturnData(err) {
|
|
|
2209
2145
|
const s = anyErr?.details ?? anyErr?.cause?.details ?? anyErr?.shortMessage ?? anyErr?.message ?? String(err);
|
|
2210
2146
|
return s.match(/return data:\s*(0x[a-fA-F0-9]+)/)?.[1];
|
|
2211
2147
|
}
|
|
2212
|
-
var
|
|
2148
|
+
var checkACPValidityAbi = [
|
|
2213
2149
|
{
|
|
2214
2150
|
type: "function",
|
|
2215
|
-
name: "
|
|
2151
|
+
name: "checkPermissionValidity",
|
|
2216
2152
|
inputs: [
|
|
2217
2153
|
{
|
|
2218
|
-
name: "
|
|
2154
|
+
name: "acp",
|
|
2219
2155
|
type: "tuple",
|
|
2220
|
-
internalType: "struct
|
|
2156
|
+
internalType: "struct ACP",
|
|
2221
2157
|
components: [
|
|
2222
2158
|
{
|
|
2223
2159
|
name: "issuer",
|
|
@@ -2235,15 +2171,30 @@ var checkPermitValidityAbi = [
|
|
|
2235
2171
|
internalType: "address"
|
|
2236
2172
|
},
|
|
2237
2173
|
{
|
|
2238
|
-
name: "
|
|
2174
|
+
name: "revokerData",
|
|
2239
2175
|
type: "uint256",
|
|
2240
2176
|
internalType: "uint256"
|
|
2241
2177
|
},
|
|
2242
2178
|
{
|
|
2243
|
-
name: "
|
|
2179
|
+
name: "revokerContract",
|
|
2244
2180
|
type: "address",
|
|
2245
2181
|
internalType: "address"
|
|
2246
2182
|
},
|
|
2183
|
+
{
|
|
2184
|
+
name: "scope",
|
|
2185
|
+
type: "uint8",
|
|
2186
|
+
internalType: "uint8"
|
|
2187
|
+
},
|
|
2188
|
+
{
|
|
2189
|
+
name: "contracts",
|
|
2190
|
+
type: "address[]",
|
|
2191
|
+
internalType: "address[]"
|
|
2192
|
+
},
|
|
2193
|
+
{
|
|
2194
|
+
name: "handles",
|
|
2195
|
+
type: "bytes32[]",
|
|
2196
|
+
internalType: "bytes32[]"
|
|
2197
|
+
},
|
|
2247
2198
|
{
|
|
2248
2199
|
name: "sealingKey",
|
|
2249
2200
|
type: "bytes32",
|
|
@@ -2293,38 +2244,40 @@ var checkPermitValidityAbi = [
|
|
|
2293
2244
|
}
|
|
2294
2245
|
];
|
|
2295
2246
|
|
|
2296
|
-
//
|
|
2297
|
-
var
|
|
2247
|
+
// acps/acp.ts
|
|
2248
|
+
var ACPUtils = {
|
|
2298
2249
|
/**
|
|
2299
|
-
* Create a self
|
|
2250
|
+
* Create a self acp for personal use
|
|
2300
2251
|
*/
|
|
2301
2252
|
createSelf: (options) => {
|
|
2302
|
-
const validation =
|
|
2253
|
+
const validation = validateSelfACPOptions(options);
|
|
2303
2254
|
const sealingPair = GenerateSealingKey();
|
|
2304
|
-
const
|
|
2305
|
-
hash:
|
|
2255
|
+
const acp = {
|
|
2256
|
+
hash: ACPUtils.getHash(validation),
|
|
2306
2257
|
...validation,
|
|
2307
|
-
sealingPair,
|
|
2258
|
+
sealingPrivateKey: sealingPair.privateKey,
|
|
2259
|
+
sealingKey: sealingPair.publicKey,
|
|
2308
2260
|
_signedDomain: void 0
|
|
2309
2261
|
};
|
|
2310
|
-
return
|
|
2262
|
+
return acp;
|
|
2311
2263
|
},
|
|
2312
2264
|
/**
|
|
2313
|
-
* Create a sharing
|
|
2265
|
+
* Create a sharing acp to be shared with another user
|
|
2314
2266
|
*/
|
|
2315
2267
|
createSharing: (options) => {
|
|
2316
|
-
const validation =
|
|
2268
|
+
const validation = validateSharingACPOptions(options);
|
|
2317
2269
|
const sealingPair = GenerateSealingKey();
|
|
2318
|
-
const
|
|
2319
|
-
hash:
|
|
2270
|
+
const acp = {
|
|
2271
|
+
hash: ACPUtils.getHash(validation),
|
|
2320
2272
|
...validation,
|
|
2321
|
-
sealingPair,
|
|
2273
|
+
sealingPrivateKey: sealingPair.privateKey,
|
|
2274
|
+
sealingKey: sealingPair.publicKey,
|
|
2322
2275
|
_signedDomain: void 0
|
|
2323
2276
|
};
|
|
2324
|
-
return
|
|
2277
|
+
return acp;
|
|
2325
2278
|
},
|
|
2326
2279
|
/**
|
|
2327
|
-
* Import a shared
|
|
2280
|
+
* Import a shared acp from various input formats
|
|
2328
2281
|
*/
|
|
2329
2282
|
importShared: (options) => {
|
|
2330
2283
|
let parsedOptions;
|
|
@@ -2337,33 +2290,34 @@ var PermitUtils = {
|
|
|
2337
2290
|
} else if (typeof options === "object" && options !== null) {
|
|
2338
2291
|
parsedOptions = options;
|
|
2339
2292
|
} else {
|
|
2340
|
-
throw new Error("Invalid input type, expected
|
|
2293
|
+
throw new Error("Invalid input type, expected ImportSharedACPOptions, object, or string");
|
|
2341
2294
|
}
|
|
2342
2295
|
if (parsedOptions.type != null && parsedOptions.type !== "sharing") {
|
|
2343
|
-
throw new Error(`Invalid
|
|
2296
|
+
throw new Error(`Invalid acp type <${parsedOptions.type}>, must be "sharing"`);
|
|
2344
2297
|
}
|
|
2345
|
-
const validation =
|
|
2298
|
+
const validation = validateImportACPOptions({ ...parsedOptions, type: "recipient" });
|
|
2346
2299
|
const sealingPair = GenerateSealingKey();
|
|
2347
|
-
const
|
|
2348
|
-
hash:
|
|
2300
|
+
const acp = {
|
|
2301
|
+
hash: ACPUtils.getHash(validation),
|
|
2349
2302
|
...validation,
|
|
2350
|
-
sealingPair,
|
|
2303
|
+
sealingPrivateKey: sealingPair.privateKey,
|
|
2304
|
+
sealingKey: sealingPair.publicKey,
|
|
2351
2305
|
_signedDomain: void 0
|
|
2352
2306
|
};
|
|
2353
|
-
return
|
|
2307
|
+
return acp;
|
|
2354
2308
|
},
|
|
2355
2309
|
/**
|
|
2356
|
-
* Sign
|
|
2310
|
+
* Sign an ACP with the provided wallet client
|
|
2357
2311
|
*/
|
|
2358
|
-
sign: async (
|
|
2312
|
+
sign: async (acp, publicClient, walletClient) => {
|
|
2359
2313
|
if (walletClient == null || walletClient.account == null) {
|
|
2360
2314
|
throw new Error(
|
|
2361
|
-
"Missing walletClient, you must pass in a `walletClient` for the connected user to create
|
|
2315
|
+
"Missing walletClient, you must pass in a `walletClient` for the connected user to create an ACP signature"
|
|
2362
2316
|
);
|
|
2363
2317
|
}
|
|
2364
|
-
const primaryType = SignatureUtils.getPrimaryType(
|
|
2318
|
+
const primaryType = SignatureUtils.getPrimaryType(acp.type);
|
|
2365
2319
|
const domain = await getAclEIP712Domain(publicClient);
|
|
2366
|
-
const { types, message } = SignatureUtils.getSignatureParams(
|
|
2320
|
+
const { types, message } = SignatureUtils.getSignatureParams(ACPUtils.getPublic(acp, true), primaryType);
|
|
2367
2321
|
const signature = await walletClient.signTypedData({
|
|
2368
2322
|
domain,
|
|
2369
2323
|
types,
|
|
@@ -2371,190 +2325,209 @@ var PermitUtils = {
|
|
|
2371
2325
|
message,
|
|
2372
2326
|
account: walletClient.account
|
|
2373
2327
|
});
|
|
2374
|
-
let
|
|
2375
|
-
if (
|
|
2376
|
-
|
|
2377
|
-
...
|
|
2328
|
+
let updatedACP;
|
|
2329
|
+
if (acp.type === "self" || acp.type === "sharing") {
|
|
2330
|
+
updatedACP = {
|
|
2331
|
+
...acp,
|
|
2378
2332
|
issuerSignature: signature,
|
|
2379
2333
|
_signedDomain: domain
|
|
2380
2334
|
};
|
|
2381
2335
|
} else {
|
|
2382
|
-
|
|
2383
|
-
...
|
|
2336
|
+
updatedACP = {
|
|
2337
|
+
...acp,
|
|
2384
2338
|
recipientSignature: signature,
|
|
2385
2339
|
_signedDomain: domain
|
|
2386
2340
|
};
|
|
2387
2341
|
}
|
|
2388
|
-
return
|
|
2342
|
+
return updatedACP;
|
|
2389
2343
|
},
|
|
2390
2344
|
/**
|
|
2391
|
-
* Create and sign a self
|
|
2345
|
+
* Create and sign a self acp in one operation
|
|
2392
2346
|
*/
|
|
2393
2347
|
createSelfAndSign: async (options, publicClient, walletClient) => {
|
|
2394
|
-
const
|
|
2395
|
-
return
|
|
2348
|
+
const acp = ACPUtils.createSelf(options);
|
|
2349
|
+
return ACPUtils.sign(acp, publicClient, walletClient);
|
|
2396
2350
|
},
|
|
2397
2351
|
/**
|
|
2398
|
-
* Create and sign a sharing
|
|
2352
|
+
* Create and sign a sharing acp in one operation
|
|
2399
2353
|
*/
|
|
2400
2354
|
createSharingAndSign: async (options, publicClient, walletClient) => {
|
|
2401
|
-
const
|
|
2402
|
-
return
|
|
2355
|
+
const acp = ACPUtils.createSharing(options);
|
|
2356
|
+
return ACPUtils.sign(acp, publicClient, walletClient);
|
|
2403
2357
|
},
|
|
2404
2358
|
/**
|
|
2405
|
-
* Import and sign a shared
|
|
2359
|
+
* Import and sign a shared acp in one operation from various input formats
|
|
2406
2360
|
*/
|
|
2407
2361
|
importSharedAndSign: async (options, publicClient, walletClient) => {
|
|
2408
|
-
const
|
|
2409
|
-
return
|
|
2362
|
+
const acp = ACPUtils.importShared(options);
|
|
2363
|
+
return ACPUtils.sign(acp, publicClient, walletClient);
|
|
2410
2364
|
},
|
|
2411
2365
|
/**
|
|
2412
|
-
* Deserialize
|
|
2366
|
+
* Deserialize an ACP from serialized data
|
|
2413
2367
|
*/
|
|
2414
2368
|
deserialize: (data) => {
|
|
2415
|
-
return {
|
|
2416
|
-
...data,
|
|
2417
|
-
sealingPair: SealingKey.deserialize(data.sealingPair.privateKey, data.sealingPair.publicKey)
|
|
2418
|
-
};
|
|
2369
|
+
return { ...data };
|
|
2419
2370
|
},
|
|
2420
2371
|
/**
|
|
2421
|
-
* Serialize
|
|
2372
|
+
* Serialize an ACP for storage
|
|
2422
2373
|
*/
|
|
2423
|
-
serialize: (
|
|
2374
|
+
serialize: (acp) => {
|
|
2424
2375
|
return {
|
|
2425
|
-
hash:
|
|
2426
|
-
name:
|
|
2427
|
-
type:
|
|
2428
|
-
issuer:
|
|
2429
|
-
expiration:
|
|
2430
|
-
recipient:
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2376
|
+
hash: acp.hash,
|
|
2377
|
+
name: acp.name,
|
|
2378
|
+
type: acp.type,
|
|
2379
|
+
issuer: acp.issuer,
|
|
2380
|
+
expiration: acp.expiration,
|
|
2381
|
+
recipient: acp.recipient,
|
|
2382
|
+
revokerData: acp.revokerData,
|
|
2383
|
+
revokerContract: acp.revokerContract,
|
|
2384
|
+
scope: acp.scope,
|
|
2385
|
+
contracts: acp.contracts,
|
|
2386
|
+
handles: acp.handles,
|
|
2387
|
+
sealingKey: acp.sealingKey,
|
|
2388
|
+
issuerSignature: acp.issuerSignature,
|
|
2389
|
+
recipientSignature: acp.recipientSignature,
|
|
2390
|
+
_signedDomain: acp._signedDomain,
|
|
2391
|
+
sealingPrivateKey: acp.sealingPrivateKey
|
|
2437
2392
|
};
|
|
2438
2393
|
},
|
|
2439
2394
|
/**
|
|
2440
|
-
* Validate
|
|
2395
|
+
* Validate an ACP (schema-level validation)
|
|
2441
2396
|
*/
|
|
2442
|
-
validateSchema: (
|
|
2443
|
-
if (
|
|
2444
|
-
return
|
|
2445
|
-
} else if (
|
|
2446
|
-
return
|
|
2447
|
-
} else if (
|
|
2448
|
-
return
|
|
2397
|
+
validateSchema: (acp) => {
|
|
2398
|
+
if (acp.type === "self") {
|
|
2399
|
+
return validateSelfACP(acp);
|
|
2400
|
+
} else if (acp.type === "sharing") {
|
|
2401
|
+
return validateSharingACP(acp);
|
|
2402
|
+
} else if (acp.type === "recipient") {
|
|
2403
|
+
return validateImportACP(acp);
|
|
2449
2404
|
} else {
|
|
2450
|
-
throw new Error("Invalid
|
|
2405
|
+
throw new Error("Invalid ACP type");
|
|
2451
2406
|
}
|
|
2452
2407
|
},
|
|
2453
2408
|
/**
|
|
2454
|
-
* Validate
|
|
2409
|
+
* Validate an ACP (holistic validation).
|
|
2455
2410
|
*
|
|
2456
2411
|
* This validates:
|
|
2457
|
-
* -
|
|
2458
|
-
* -
|
|
2459
|
-
* -
|
|
2412
|
+
* - ACP schema (shape + invariants)
|
|
2413
|
+
* - ACP is signed
|
|
2414
|
+
* - ACP is not expired
|
|
2460
2415
|
*
|
|
2461
|
-
* For schema-only validation, use `validateSchema(
|
|
2416
|
+
* For schema-only validation, use `validateSchema(acp)`.
|
|
2462
2417
|
*/
|
|
2463
|
-
validate: (
|
|
2464
|
-
const validated =
|
|
2418
|
+
validate: (acp) => {
|
|
2419
|
+
const validated = ACPUtils.validateSchema(acp);
|
|
2465
2420
|
ValidationUtils.assertSignedAndNotExpired(validated);
|
|
2466
2421
|
return validated;
|
|
2467
2422
|
},
|
|
2468
2423
|
/**
|
|
2469
|
-
* Get the
|
|
2424
|
+
* Get the public component of an ACP — the signed struct sent on-chain / to the decryption backend.
|
|
2425
|
+
* Strips the private component (hash, name, type, sealing pair).
|
|
2470
2426
|
*/
|
|
2471
|
-
|
|
2427
|
+
getPublic: (acp, skipValidation = false) => {
|
|
2472
2428
|
if (!skipValidation) {
|
|
2473
|
-
|
|
2429
|
+
ACPUtils.validateSchema(acp);
|
|
2474
2430
|
}
|
|
2475
2431
|
return {
|
|
2476
|
-
issuer:
|
|
2477
|
-
expiration:
|
|
2478
|
-
recipient:
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2432
|
+
issuer: acp.issuer,
|
|
2433
|
+
expiration: acp.expiration,
|
|
2434
|
+
recipient: acp.recipient,
|
|
2435
|
+
revokerData: acp.revokerData,
|
|
2436
|
+
revokerContract: acp.revokerContract,
|
|
2437
|
+
scope: acp.scope,
|
|
2438
|
+
contracts: acp.contracts,
|
|
2439
|
+
handles: acp.handles,
|
|
2440
|
+
sealingKey: acp.sealingKey,
|
|
2441
|
+
issuerSignature: acp.issuerSignature,
|
|
2442
|
+
recipientSignature: acp.recipientSignature
|
|
2484
2443
|
};
|
|
2485
2444
|
},
|
|
2486
2445
|
/**
|
|
2487
|
-
* Get a stable hash for the
|
|
2446
|
+
* Get a stable hash for the acp (used as key in storage)
|
|
2488
2447
|
*/
|
|
2489
|
-
getHash: (
|
|
2448
|
+
getHash: (acp) => {
|
|
2490
2449
|
const data = JSON.stringify({
|
|
2491
|
-
type:
|
|
2492
|
-
issuer:
|
|
2493
|
-
expiration:
|
|
2494
|
-
recipient:
|
|
2495
|
-
|
|
2496
|
-
|
|
2450
|
+
type: acp.type,
|
|
2451
|
+
issuer: acp.issuer,
|
|
2452
|
+
expiration: acp.expiration,
|
|
2453
|
+
recipient: acp.recipient,
|
|
2454
|
+
revokerData: acp.revokerData,
|
|
2455
|
+
revokerContract: acp.revokerContract,
|
|
2456
|
+
scope: acp.scope,
|
|
2457
|
+
contracts: acp.contracts,
|
|
2458
|
+
handles: acp.handles
|
|
2497
2459
|
});
|
|
2498
2460
|
return viem.keccak256(viem.toHex(data));
|
|
2499
2461
|
},
|
|
2500
2462
|
/**
|
|
2501
|
-
* Export
|
|
2463
|
+
* Export acp data for sharing (strips the private component).
|
|
2464
|
+
* Fixed `SharedACP` shape — every field always present, aligned with
|
|
2465
|
+
* `ACPPublic` and the on-chain sharing payload.
|
|
2502
2466
|
*/
|
|
2503
|
-
export: (
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2467
|
+
export: (acp) => {
|
|
2468
|
+
if (acp.type !== "sharing") {
|
|
2469
|
+
throw new Error(
|
|
2470
|
+
`Cannot export a '${acp.type}' ACP \u2014 only 'sharing' ACPs are exportable. The export includes the issuer signature.`
|
|
2471
|
+
);
|
|
2472
|
+
}
|
|
2473
|
+
if (acp.issuerSignature === "0x") {
|
|
2474
|
+
throw new Error(
|
|
2475
|
+
"Cannot export an unsigned sharing ACP \u2014 sign it first (the recipient needs the issuer signature)."
|
|
2476
|
+
);
|
|
2477
|
+
}
|
|
2478
|
+
const shared = {
|
|
2479
|
+
name: acp.name,
|
|
2480
|
+
type: acp.type,
|
|
2481
|
+
issuer: acp.issuer,
|
|
2482
|
+
expiration: acp.expiration,
|
|
2483
|
+
recipient: acp.recipient,
|
|
2484
|
+
revokerData: acp.revokerData,
|
|
2485
|
+
revokerContract: acp.revokerContract,
|
|
2486
|
+
scope: acp.scope,
|
|
2487
|
+
contracts: acp.contracts,
|
|
2488
|
+
handles: acp.handles,
|
|
2489
|
+
issuerSignature: acp.issuerSignature
|
|
2509
2490
|
};
|
|
2510
|
-
|
|
2511
|
-
cleanedPermit.recipient = permit.recipient;
|
|
2512
|
-
if (permit.validatorId !== 0)
|
|
2513
|
-
cleanedPermit.validatorId = permit.validatorId;
|
|
2514
|
-
if (permit.validatorContract !== viem.zeroAddress)
|
|
2515
|
-
cleanedPermit.validatorContract = permit.validatorContract;
|
|
2516
|
-
if (permit.type === "sharing" && permit.issuerSignature !== "0x")
|
|
2517
|
-
cleanedPermit.issuerSignature = permit.issuerSignature;
|
|
2518
|
-
return JSON.stringify(cleanedPermit, void 0, 2);
|
|
2491
|
+
return JSON.stringify(shared, void 0, 2);
|
|
2519
2492
|
},
|
|
2520
2493
|
/**
|
|
2521
|
-
* Unseal encrypted data using the
|
|
2494
|
+
* Unseal encrypted data using the acp's sealing key
|
|
2522
2495
|
*/
|
|
2523
|
-
unseal: (
|
|
2524
|
-
return
|
|
2496
|
+
unseal: (acp, ciphertext) => {
|
|
2497
|
+
return unsealWithPrivateKey(acp.sealingPrivateKey, ciphertext);
|
|
2525
2498
|
},
|
|
2526
2499
|
/**
|
|
2527
|
-
* Check if
|
|
2500
|
+
* Check if acp is expired
|
|
2528
2501
|
*/
|
|
2529
|
-
isExpired: (
|
|
2530
|
-
return ValidationUtils.isExpired(
|
|
2502
|
+
isExpired: (acp) => {
|
|
2503
|
+
return ValidationUtils.isExpired(acp);
|
|
2531
2504
|
},
|
|
2532
2505
|
/**
|
|
2533
|
-
* Check if
|
|
2506
|
+
* Check if acp is signed
|
|
2534
2507
|
*/
|
|
2535
|
-
isSigned: (
|
|
2536
|
-
return ValidationUtils.isSigned(
|
|
2508
|
+
isSigned: (acp) => {
|
|
2509
|
+
return ValidationUtils.isSigned(acp);
|
|
2537
2510
|
},
|
|
2538
2511
|
/**
|
|
2539
|
-
* Check if
|
|
2512
|
+
* Check if acp is signed and not expired
|
|
2540
2513
|
*/
|
|
2541
|
-
isSignedAndNotExpired: (
|
|
2542
|
-
return ValidationUtils.isSignedAndNotExpired(
|
|
2514
|
+
isSignedAndNotExpired: (acp) => {
|
|
2515
|
+
return ValidationUtils.isSignedAndNotExpired(acp);
|
|
2543
2516
|
},
|
|
2544
2517
|
/**
|
|
2545
|
-
* Assert that
|
|
2518
|
+
* Assert that acp is signed and not expired
|
|
2546
2519
|
*/
|
|
2547
|
-
assertSignedAndNotExpired: (
|
|
2548
|
-
return ValidationUtils.assertSignedAndNotExpired(
|
|
2520
|
+
assertSignedAndNotExpired: (acp) => {
|
|
2521
|
+
return ValidationUtils.assertSignedAndNotExpired(acp);
|
|
2549
2522
|
},
|
|
2550
|
-
isValid: (
|
|
2551
|
-
return ValidationUtils.isValid(
|
|
2523
|
+
isValid: (acp) => {
|
|
2524
|
+
return ValidationUtils.isValid(acp);
|
|
2552
2525
|
},
|
|
2553
2526
|
/**
|
|
2554
|
-
* Update
|
|
2527
|
+
* Update acp name (returns new acp instance)
|
|
2555
2528
|
*/
|
|
2556
|
-
updateName: (
|
|
2557
|
-
return { ...
|
|
2529
|
+
updateName: (acp, name) => {
|
|
2530
|
+
return { ...acp, name };
|
|
2558
2531
|
},
|
|
2559
2532
|
/**
|
|
2560
2533
|
* Fetch EIP712 domain from the blockchain
|
|
@@ -2563,230 +2536,468 @@ var PermitUtils = {
|
|
|
2563
2536
|
return getAclEIP712Domain(publicClient);
|
|
2564
2537
|
},
|
|
2565
2538
|
/**
|
|
2566
|
-
* Check if
|
|
2539
|
+
* Check if acp's signed domain matches the provided domain
|
|
2567
2540
|
*/
|
|
2568
|
-
matchesDomain: (
|
|
2569
|
-
return
|
|
2541
|
+
matchesDomain: (acp, domain) => {
|
|
2542
|
+
return acp._signedDomain?.name === domain.name && acp._signedDomain?.version === domain.version && acp._signedDomain?.verifyingContract === domain.verifyingContract && acp._signedDomain?.chainId === domain.chainId;
|
|
2570
2543
|
},
|
|
2571
2544
|
/**
|
|
2572
|
-
* Check if
|
|
2545
|
+
* Check if acp's signed domain is valid for the current chain
|
|
2573
2546
|
*/
|
|
2574
|
-
checkSignedDomainValid: async (
|
|
2575
|
-
if (
|
|
2547
|
+
checkSignedDomainValid: async (acp, publicClient) => {
|
|
2548
|
+
if (acp._signedDomain == null)
|
|
2576
2549
|
return false;
|
|
2577
2550
|
const domain = await getAclEIP712Domain(publicClient);
|
|
2578
|
-
return
|
|
2551
|
+
return ACPUtils.matchesDomain(acp, domain);
|
|
2579
2552
|
},
|
|
2580
2553
|
/**
|
|
2581
|
-
* Check if
|
|
2554
|
+
* Check if acp passes the on-chain validation
|
|
2582
2555
|
*/
|
|
2583
|
-
checkValidityOnChain: async (
|
|
2584
|
-
const
|
|
2585
|
-
return
|
|
2556
|
+
checkValidityOnChain: async (acp, publicClient) => {
|
|
2557
|
+
const publicAcp = ACPUtils.getPublic(acp);
|
|
2558
|
+
return checkACPValidityOnChain(publicAcp, publicClient);
|
|
2586
2559
|
}
|
|
2587
2560
|
};
|
|
2588
|
-
var
|
|
2589
|
-
|
|
2590
|
-
|
|
2561
|
+
var ACP_STORE_DEFAULTS = {
|
|
2562
|
+
acps: {},
|
|
2563
|
+
activeACPHash: {}
|
|
2591
2564
|
};
|
|
2592
|
-
var
|
|
2593
|
-
|
|
2565
|
+
var ACP_STORE_VERSION = 3;
|
|
2566
|
+
var _acpStore = vanilla.createStore()(
|
|
2567
|
+
middleware.persist(() => ACP_STORE_DEFAULTS, {
|
|
2568
|
+
name: "cofhesdk-acps",
|
|
2569
|
+
version: ACP_STORE_VERSION,
|
|
2570
|
+
migrate: (persistedState, version) => {
|
|
2571
|
+
if (version < ACP_STORE_VERSION)
|
|
2572
|
+
return ACP_STORE_DEFAULTS;
|
|
2573
|
+
return persistedState;
|
|
2574
|
+
}
|
|
2575
|
+
})
|
|
2594
2576
|
);
|
|
2595
2577
|
var clearStaleStore = () => {
|
|
2596
|
-
const state =
|
|
2597
|
-
const hasExpectedStructure = state && typeof state === "object" && "
|
|
2578
|
+
const state = _acpStore.getState();
|
|
2579
|
+
const hasExpectedStructure = state && typeof state === "object" && "acps" in state && "activeACPHash" in state && typeof state.acps === "object" && typeof state.activeACPHash === "object";
|
|
2598
2580
|
if (hasExpectedStructure)
|
|
2599
2581
|
return;
|
|
2600
|
-
|
|
2582
|
+
_acpStore.setState({ acps: {}, activeACPHash: {} });
|
|
2601
2583
|
};
|
|
2602
|
-
var
|
|
2584
|
+
var getACP = (chainId, account, hash) => {
|
|
2603
2585
|
clearStaleStore();
|
|
2604
2586
|
if (chainId == null || account == null || hash == null)
|
|
2605
2587
|
return;
|
|
2606
|
-
const
|
|
2607
|
-
if (
|
|
2588
|
+
const savedACP = _acpStore.getState().acps[chainId]?.[account]?.[hash];
|
|
2589
|
+
if (savedACP == null)
|
|
2608
2590
|
return;
|
|
2609
|
-
return
|
|
2591
|
+
return ACPUtils.deserialize(savedACP);
|
|
2610
2592
|
};
|
|
2611
|
-
var
|
|
2593
|
+
var getActiveACP = (chainId, account) => {
|
|
2612
2594
|
clearStaleStore();
|
|
2613
2595
|
if (chainId == null || account == null)
|
|
2614
2596
|
return;
|
|
2615
|
-
const
|
|
2616
|
-
return
|
|
2597
|
+
const activeACPHash = _acpStore.getState().activeACPHash[chainId]?.[account];
|
|
2598
|
+
return getACP(chainId, account, activeACPHash);
|
|
2617
2599
|
};
|
|
2618
|
-
var
|
|
2600
|
+
var getACPs = (chainId, account) => {
|
|
2619
2601
|
clearStaleStore();
|
|
2620
2602
|
if (chainId == null || account == null)
|
|
2621
2603
|
return {};
|
|
2622
|
-
return Object.entries(
|
|
2623
|
-
(acc, [hash,
|
|
2624
|
-
if (
|
|
2604
|
+
return Object.entries(_acpStore.getState().acps[chainId]?.[account] ?? {}).reduce(
|
|
2605
|
+
(acc, [hash, acp]) => {
|
|
2606
|
+
if (acp == void 0)
|
|
2625
2607
|
return acc;
|
|
2626
|
-
return { ...acc, [hash]:
|
|
2608
|
+
return { ...acc, [hash]: ACPUtils.deserialize(acp) };
|
|
2627
2609
|
},
|
|
2628
2610
|
{}
|
|
2629
2611
|
);
|
|
2630
2612
|
};
|
|
2631
|
-
var
|
|
2613
|
+
var setACP = (chainId, account, acp) => {
|
|
2632
2614
|
clearStaleStore();
|
|
2633
|
-
|
|
2615
|
+
_acpStore.setState(
|
|
2634
2616
|
immer.produce((state) => {
|
|
2635
|
-
if (state.
|
|
2636
|
-
state.
|
|
2637
|
-
if (state.
|
|
2638
|
-
state.
|
|
2639
|
-
state.
|
|
2617
|
+
if (state.acps[chainId] == null)
|
|
2618
|
+
state.acps[chainId] = {};
|
|
2619
|
+
if (state.acps[chainId][account] == null)
|
|
2620
|
+
state.acps[chainId][account] = {};
|
|
2621
|
+
state.acps[chainId][account][acp.hash] = ACPUtils.serialize(acp);
|
|
2640
2622
|
})
|
|
2641
2623
|
);
|
|
2642
2624
|
};
|
|
2643
|
-
var
|
|
2625
|
+
var removeACP = (chainId, account, hash) => {
|
|
2644
2626
|
clearStaleStore();
|
|
2645
|
-
|
|
2627
|
+
_acpStore.setState(
|
|
2646
2628
|
immer.produce((state) => {
|
|
2647
|
-
if (state.
|
|
2648
|
-
state.
|
|
2649
|
-
if (state.
|
|
2650
|
-
state.
|
|
2651
|
-
const
|
|
2652
|
-
if (
|
|
2629
|
+
if (state.acps[chainId] == null)
|
|
2630
|
+
state.acps[chainId] = {};
|
|
2631
|
+
if (state.activeACPHash[chainId] == null)
|
|
2632
|
+
state.activeACPHash[chainId] = {};
|
|
2633
|
+
const accountACPs = state.acps[chainId][account];
|
|
2634
|
+
if (accountACPs == null)
|
|
2653
2635
|
return;
|
|
2654
|
-
if (
|
|
2636
|
+
if (accountACPs[hash] == null)
|
|
2655
2637
|
return;
|
|
2656
|
-
if (state.
|
|
2657
|
-
state.
|
|
2638
|
+
if (state.activeACPHash[chainId][account] === hash) {
|
|
2639
|
+
state.activeACPHash[chainId][account] = void 0;
|
|
2658
2640
|
}
|
|
2659
|
-
|
|
2641
|
+
accountACPs[hash] = void 0;
|
|
2660
2642
|
})
|
|
2661
2643
|
);
|
|
2662
2644
|
};
|
|
2663
|
-
var
|
|
2645
|
+
var getActiveACPHash = (chainId, account) => {
|
|
2664
2646
|
clearStaleStore();
|
|
2665
2647
|
if (chainId == null || account == null)
|
|
2666
2648
|
return void 0;
|
|
2667
|
-
return
|
|
2649
|
+
return _acpStore.getState().activeACPHash[chainId]?.[account];
|
|
2668
2650
|
};
|
|
2669
|
-
var
|
|
2651
|
+
var setActiveACPHash = (chainId, account, hash) => {
|
|
2670
2652
|
clearStaleStore();
|
|
2671
|
-
|
|
2653
|
+
_acpStore.setState(
|
|
2672
2654
|
immer.produce((state) => {
|
|
2673
|
-
if (state.
|
|
2674
|
-
state.
|
|
2675
|
-
state.
|
|
2655
|
+
if (state.activeACPHash[chainId] == null)
|
|
2656
|
+
state.activeACPHash[chainId] = {};
|
|
2657
|
+
state.activeACPHash[chainId][account] = hash;
|
|
2676
2658
|
})
|
|
2677
2659
|
);
|
|
2678
2660
|
};
|
|
2679
|
-
var
|
|
2661
|
+
var removeActiveACPHash = (chainId, account) => {
|
|
2680
2662
|
clearStaleStore();
|
|
2681
|
-
|
|
2663
|
+
_acpStore.setState(
|
|
2682
2664
|
immer.produce((state) => {
|
|
2683
|
-
if (state.
|
|
2684
|
-
state.
|
|
2665
|
+
if (state.activeACPHash[chainId])
|
|
2666
|
+
state.activeACPHash[chainId][account] = void 0;
|
|
2685
2667
|
})
|
|
2686
2668
|
);
|
|
2687
2669
|
};
|
|
2688
2670
|
var resetStore = () => {
|
|
2689
2671
|
clearStaleStore();
|
|
2690
|
-
|
|
2672
|
+
_acpStore.setState({ acps: {}, activeACPHash: {} });
|
|
2691
2673
|
};
|
|
2692
|
-
var
|
|
2693
|
-
store:
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2674
|
+
var acpStore = {
|
|
2675
|
+
store: _acpStore,
|
|
2676
|
+
getACP,
|
|
2677
|
+
getActiveACP,
|
|
2678
|
+
getACPs,
|
|
2679
|
+
setACP,
|
|
2680
|
+
removeACP,
|
|
2681
|
+
getActiveACPHash,
|
|
2682
|
+
setActiveACPHash,
|
|
2683
|
+
removeActiveACPHash,
|
|
2702
2684
|
resetStore
|
|
2703
2685
|
};
|
|
2704
|
-
var
|
|
2686
|
+
var ACP_VALIDATOR_ABI = viem.parseAbi([
|
|
2687
|
+
"function revokeSingle(uint256 id)",
|
|
2688
|
+
"function revokeAllExisting()",
|
|
2689
|
+
"function disabled(address issuer, uint256 id) view returns (bool)"
|
|
2690
|
+
]);
|
|
2691
|
+
var storeACP = async (acp, publicClient, walletClient) => {
|
|
2705
2692
|
const chainId = await publicClient.getChainId();
|
|
2706
2693
|
const account = walletClient.account.address;
|
|
2707
|
-
|
|
2708
|
-
permitStore.setActivePermitHash(chainId, account, permit.hash);
|
|
2694
|
+
acpStore.setACP(chainId, account, acp);
|
|
2709
2695
|
};
|
|
2710
|
-
var
|
|
2711
|
-
|
|
2712
|
-
await
|
|
2713
|
-
|
|
2696
|
+
var storeActiveACP = async (acp, publicClient, walletClient) => {
|
|
2697
|
+
await storeACP(acp, publicClient, walletClient);
|
|
2698
|
+
const chainId = await publicClient.getChainId();
|
|
2699
|
+
const account = walletClient.account.address;
|
|
2700
|
+
acpStore.setActiveACPHash(chainId, account, acp.hash);
|
|
2701
|
+
};
|
|
2702
|
+
var createACPWithSign = async (options, publicClient, walletClient, acpMethod, activate = true) => {
|
|
2703
|
+
const acp = await acpMethod(options, publicClient, walletClient);
|
|
2704
|
+
if (activate) {
|
|
2705
|
+
await storeActiveACP(acp, publicClient, walletClient);
|
|
2706
|
+
} else {
|
|
2707
|
+
await storeACP(acp, publicClient, walletClient);
|
|
2708
|
+
}
|
|
2709
|
+
return acp;
|
|
2714
2710
|
};
|
|
2715
2711
|
var createSelf = async (options, publicClient, walletClient) => {
|
|
2716
|
-
return
|
|
2712
|
+
return createACPWithSign(options, publicClient, walletClient, ACPUtils.createSelfAndSign);
|
|
2717
2713
|
};
|
|
2718
2714
|
var createSharing = async (options, publicClient, walletClient) => {
|
|
2719
|
-
return
|
|
2715
|
+
return createACPWithSign(options, publicClient, walletClient, ACPUtils.createSharingAndSign, false);
|
|
2720
2716
|
};
|
|
2721
2717
|
var importShared = async (options, publicClient, walletClient) => {
|
|
2722
|
-
return
|
|
2718
|
+
return createACPWithSign(options, publicClient, walletClient, ACPUtils.importSharedAndSign);
|
|
2723
2719
|
};
|
|
2724
|
-
var getHash = (
|
|
2725
|
-
return
|
|
2720
|
+
var getHash = (acp) => {
|
|
2721
|
+
return ACPUtils.getHash(acp);
|
|
2726
2722
|
};
|
|
2727
|
-
var exportShared = (
|
|
2728
|
-
return
|
|
2723
|
+
var exportShared = (acp) => {
|
|
2724
|
+
return ACPUtils.export(acp);
|
|
2729
2725
|
};
|
|
2730
|
-
var serialize = (
|
|
2731
|
-
return
|
|
2726
|
+
var serialize = (acp) => {
|
|
2727
|
+
return ACPUtils.serialize(acp);
|
|
2732
2728
|
};
|
|
2733
2729
|
var deserialize = (serialized) => {
|
|
2734
|
-
return
|
|
2730
|
+
return ACPUtils.deserialize(serialized);
|
|
2735
2731
|
};
|
|
2736
|
-
var
|
|
2737
|
-
return
|
|
2732
|
+
var getACP2 = (chainId, account, hash) => {
|
|
2733
|
+
return acpStore.getACP(chainId, account, hash);
|
|
2738
2734
|
};
|
|
2739
|
-
var
|
|
2740
|
-
return
|
|
2735
|
+
var getACPs2 = (chainId, account) => {
|
|
2736
|
+
return acpStore.getACPs(chainId, account);
|
|
2741
2737
|
};
|
|
2742
|
-
var
|
|
2743
|
-
return
|
|
2738
|
+
var getActiveACP2 = (chainId, account) => {
|
|
2739
|
+
return acpStore.getActiveACP(chainId, account);
|
|
2744
2740
|
};
|
|
2745
|
-
var
|
|
2746
|
-
return
|
|
2741
|
+
var getActiveACPHash2 = (chainId, account) => {
|
|
2742
|
+
return acpStore.getActiveACPHash(chainId, account);
|
|
2747
2743
|
};
|
|
2748
|
-
var
|
|
2749
|
-
|
|
2744
|
+
var selectActiveACP = (chainId, account, hash) => {
|
|
2745
|
+
acpStore.setActiveACPHash(chainId, account, hash);
|
|
2750
2746
|
};
|
|
2751
|
-
var
|
|
2747
|
+
var getOrCreateSelfACP = async (publicClient, walletClient, chainId, account, options) => {
|
|
2752
2748
|
const _chainId = chainId ?? await publicClient.getChainId();
|
|
2753
2749
|
const _account = account ?? walletClient.account.address;
|
|
2754
|
-
const
|
|
2755
|
-
if (
|
|
2756
|
-
return
|
|
2750
|
+
const activeACP = await getActiveACP2(_chainId, _account);
|
|
2751
|
+
if (activeACP && activeACP.type === "self" && ACPUtils.isValid(activeACP).valid) {
|
|
2752
|
+
return activeACP;
|
|
2757
2753
|
}
|
|
2758
|
-
return createSelf(options ?? { issuer: _account, name: "Autogenerated Self
|
|
2754
|
+
return createSelf(options ?? { issuer: _account, name: "Autogenerated Self ACP" }, publicClient, walletClient);
|
|
2759
2755
|
};
|
|
2760
|
-
var
|
|
2756
|
+
var getOrCreateSharingACP = async (publicClient, walletClient, options, chainId, account) => {
|
|
2761
2757
|
const _chainId = chainId ?? await publicClient.getChainId();
|
|
2762
2758
|
const _account = account ?? walletClient.account.address;
|
|
2763
|
-
const
|
|
2764
|
-
if (
|
|
2765
|
-
return
|
|
2759
|
+
const activeACP = await getActiveACP2(_chainId, _account);
|
|
2760
|
+
if (activeACP && activeACP.type === "sharing" && ACPUtils.isValid(activeACP).valid) {
|
|
2761
|
+
return activeACP;
|
|
2766
2762
|
}
|
|
2767
2763
|
return createSharing(options, publicClient, walletClient);
|
|
2768
2764
|
};
|
|
2769
|
-
var
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2765
|
+
var applyACPDefaults = (options, acpConfig, chainId) => {
|
|
2766
|
+
const result = { ...options };
|
|
2767
|
+
const defaultRevoker = acpConfig?.defaultRevoker?.[chainId];
|
|
2768
|
+
const hasValidatorOptions = options.revokerData != null || options.revokerContract != null;
|
|
2769
|
+
if (defaultRevoker != null && !hasValidatorOptions) {
|
|
2770
|
+
result.revokerContract = defaultRevoker;
|
|
2771
|
+
result.revokerData = Math.round(Date.now() / 1e3) - 60;
|
|
2772
|
+
}
|
|
2773
|
+
const defaultContracts = acpConfig?.defaultContractScopes?.[chainId];
|
|
2774
|
+
const hasScopeOptions = options.scope != null || options.contracts != null || options.handles != null;
|
|
2775
|
+
if (defaultContracts != null && defaultContracts.length > 0 && !hasScopeOptions) {
|
|
2776
|
+
result.contracts = defaultContracts;
|
|
2777
|
+
}
|
|
2778
|
+
return result;
|
|
2779
|
+
};
|
|
2780
|
+
var ACL_SERVED_ADDRESSES_ABI = viem.parseAbi([
|
|
2781
|
+
"function acl() view returns (address)",
|
|
2782
|
+
"function defaultRevokerContract() view returns (address)",
|
|
2783
|
+
"function shareRegistry() view returns (address)"
|
|
2784
|
+
]);
|
|
2785
|
+
var aclServedAddressesCache = /* @__PURE__ */ new Map();
|
|
2786
|
+
var clearAclServedAddresses = () => aclServedAddressesCache.clear();
|
|
2787
|
+
var getAclServedAddresses = async (publicClient, chainId) => {
|
|
2788
|
+
const cached = aclServedAddressesCache.get(chainId);
|
|
2789
|
+
if (cached != null)
|
|
2790
|
+
return cached;
|
|
2791
|
+
let aclAddress;
|
|
2792
|
+
try {
|
|
2793
|
+
aclAddress = await publicClient.readContract({
|
|
2794
|
+
address: TASK_MANAGER_ADDRESS,
|
|
2795
|
+
abi: ACL_SERVED_ADDRESSES_ABI,
|
|
2796
|
+
functionName: "acl"
|
|
2797
|
+
});
|
|
2798
|
+
} catch {
|
|
2799
|
+
return {};
|
|
2800
|
+
}
|
|
2801
|
+
const [defaultRevoker, shareRegistry] = await Promise.all([
|
|
2802
|
+
publicClient.readContract({ address: aclAddress, abi: ACL_SERVED_ADDRESSES_ABI, functionName: "defaultRevokerContract" }).catch(() => void 0),
|
|
2803
|
+
publicClient.readContract({ address: aclAddress, abi: ACL_SERVED_ADDRESSES_ABI, functionName: "shareRegistry" }).catch(() => void 0)
|
|
2804
|
+
]);
|
|
2805
|
+
const resolved = {
|
|
2806
|
+
defaultRevoker: defaultRevoker != null && defaultRevoker !== viem.zeroAddress ? defaultRevoker : void 0,
|
|
2807
|
+
shareRegistry: shareRegistry != null && shareRegistry !== viem.zeroAddress ? shareRegistry : void 0
|
|
2808
|
+
};
|
|
2809
|
+
aclServedAddressesCache.set(chainId, resolved);
|
|
2810
|
+
return resolved;
|
|
2811
|
+
};
|
|
2812
|
+
var applyACPDefaultsFromChain = async (options, acpConfig, publicClient, chainId) => {
|
|
2813
|
+
const hasExplicitRevoker = acpConfig?.defaultRevoker?.[chainId] != null || options.revokerData != null || options.revokerContract != null;
|
|
2814
|
+
if (hasExplicitRevoker)
|
|
2815
|
+
return applyACPDefaults(options, acpConfig, chainId);
|
|
2816
|
+
const served = await getAclServedAddresses(publicClient, chainId);
|
|
2817
|
+
const effectiveConfig = served.defaultRevoker != null ? { ...acpConfig, defaultRevoker: { ...acpConfig?.defaultRevoker, [chainId]: served.defaultRevoker } } : acpConfig;
|
|
2818
|
+
return applyACPDefaults(options, effectiveConfig, chainId);
|
|
2819
|
+
};
|
|
2820
|
+
var revokeACP = async (acp, walletClient) => {
|
|
2821
|
+
if (acp.revokerContract === viem.zeroAddress || acp.revokerData === 0) {
|
|
2822
|
+
throw new Error("ACP is not revocable: it has no revoker (revokerContract/revokerData unset)");
|
|
2823
|
+
}
|
|
2824
|
+
if (walletClient.account == null)
|
|
2825
|
+
throw new Error("Missing walletClient account");
|
|
2826
|
+
if (walletClient.account.address.toLowerCase() !== acp.issuer.toLowerCase()) {
|
|
2827
|
+
throw new Error("Only the acp issuer can revoke it");
|
|
2828
|
+
}
|
|
2829
|
+
return walletClient.writeContract({
|
|
2830
|
+
address: acp.revokerContract,
|
|
2831
|
+
abi: ACP_VALIDATOR_ABI,
|
|
2832
|
+
functionName: "revokeSingle",
|
|
2833
|
+
args: [BigInt(acp.revokerData)],
|
|
2834
|
+
account: walletClient.account,
|
|
2835
|
+
chain: walletClient.chain
|
|
2836
|
+
});
|
|
2837
|
+
};
|
|
2838
|
+
var revokeAllACPs = async (walletClient, publicClient, revokerContract) => {
|
|
2839
|
+
if (walletClient.account == null)
|
|
2840
|
+
throw new Error("Missing walletClient account");
|
|
2841
|
+
let revoker = revokerContract;
|
|
2842
|
+
if (revoker == null) {
|
|
2843
|
+
const chainId = await publicClient.getChainId();
|
|
2844
|
+
const active = getActiveACP2(chainId, walletClient.account.address);
|
|
2845
|
+
revoker = active?.revokerContract;
|
|
2846
|
+
}
|
|
2847
|
+
if (revoker == null || revoker === viem.zeroAddress) {
|
|
2848
|
+
throw new Error("No revoker contract: pass `revokerContract` or activate a revocable acp first");
|
|
2849
|
+
}
|
|
2850
|
+
return walletClient.writeContract({
|
|
2851
|
+
address: revoker,
|
|
2852
|
+
abi: ACP_VALIDATOR_ABI,
|
|
2853
|
+
functionName: "revokeAllExisting",
|
|
2854
|
+
args: [],
|
|
2855
|
+
account: walletClient.account,
|
|
2856
|
+
chain: walletClient.chain
|
|
2857
|
+
});
|
|
2858
|
+
};
|
|
2859
|
+
var isACPRevoked = async (acp, publicClient) => {
|
|
2860
|
+
if (acp.revokerContract === viem.zeroAddress || acp.revokerData === 0)
|
|
2861
|
+
return false;
|
|
2862
|
+
return publicClient.readContract({
|
|
2863
|
+
address: acp.revokerContract,
|
|
2864
|
+
abi: ACP_VALIDATOR_ABI,
|
|
2865
|
+
functionName: "disabled",
|
|
2866
|
+
args: [acp.issuer, BigInt(acp.revokerData)]
|
|
2867
|
+
});
|
|
2868
|
+
};
|
|
2869
|
+
var ACP_SHARE_REGISTRY_ABI = viem.parseAbi([
|
|
2870
|
+
"struct ACP { address issuer; uint64 expiration; address recipient; uint256 revokerData; address revokerContract; uint8 scope; address[] contracts; bytes32[] handles; bytes32 sealingKey; bytes issuerSignature; bytes recipientSignature; }",
|
|
2871
|
+
"function share(ACP calldata acp) external returns (bytes32)",
|
|
2872
|
+
"function removeShare(bytes32 shareId) external",
|
|
2873
|
+
"function sharesFor(address recipient) external view returns (ACP[] memory)",
|
|
2874
|
+
"function getShare(bytes32 shareId) external view returns (ACP memory)",
|
|
2875
|
+
"function isShareValid(bytes32 shareId) external view returns (bool)"
|
|
2876
|
+
]);
|
|
2877
|
+
var ACP_TUPLE = [
|
|
2878
|
+
{
|
|
2879
|
+
type: "tuple",
|
|
2880
|
+
components: [
|
|
2881
|
+
{ name: "issuer", type: "address" },
|
|
2882
|
+
{ name: "expiration", type: "uint64" },
|
|
2883
|
+
{ name: "recipient", type: "address" },
|
|
2884
|
+
{ name: "revokerData", type: "uint256" },
|
|
2885
|
+
{ name: "revokerContract", type: "address" },
|
|
2886
|
+
{ name: "scope", type: "uint8" },
|
|
2887
|
+
{ name: "contracts", type: "address[]" },
|
|
2888
|
+
{ name: "handles", type: "bytes32[]" },
|
|
2889
|
+
{ name: "sealingKey", type: "bytes32" },
|
|
2890
|
+
{ name: "issuerSignature", type: "bytes" },
|
|
2891
|
+
{ name: "recipientSignature", type: "bytes" }
|
|
2892
|
+
]
|
|
2893
|
+
}
|
|
2894
|
+
];
|
|
2895
|
+
var ZERO_BYTES32 = `0x${"0".repeat(64)}`;
|
|
2896
|
+
var toChainShare = (acp) => {
|
|
2897
|
+
const pub = ACPUtils.getPublic(acp, true);
|
|
2898
|
+
return {
|
|
2899
|
+
...pub,
|
|
2900
|
+
expiration: BigInt(pub.expiration),
|
|
2901
|
+
revokerData: BigInt(pub.revokerData),
|
|
2902
|
+
sealingKey: ZERO_BYTES32,
|
|
2903
|
+
recipientSignature: "0x"
|
|
2904
|
+
};
|
|
2905
|
+
};
|
|
2906
|
+
var computeShareId = (acp) => {
|
|
2907
|
+
const p = toChainShare(acp);
|
|
2908
|
+
return viem.keccak256(viem.encodeAbiParameters(ACP_TUPLE, [p]));
|
|
2909
|
+
};
|
|
2910
|
+
var shareOnChain = async (acp, walletClient, registry) => {
|
|
2911
|
+
if (acp.type !== "sharing") {
|
|
2912
|
+
throw new Error(`Cannot share a '${acp.type}' ACP on-chain \u2014 only 'sharing' ACPs are shareable.`);
|
|
2913
|
+
}
|
|
2914
|
+
if (acp.issuerSignature === "0x") {
|
|
2915
|
+
throw new Error("Cannot share an unsigned sharing ACP \u2014 sign it first.");
|
|
2916
|
+
}
|
|
2917
|
+
if (walletClient.account == null)
|
|
2918
|
+
throw new Error("Missing walletClient account");
|
|
2919
|
+
if (walletClient.account.address.toLowerCase() !== acp.issuer.toLowerCase()) {
|
|
2920
|
+
throw new Error("Only the ACP issuer can share it on-chain");
|
|
2921
|
+
}
|
|
2922
|
+
const txHash = await walletClient.writeContract({
|
|
2923
|
+
address: registry,
|
|
2924
|
+
abi: ACP_SHARE_REGISTRY_ABI,
|
|
2925
|
+
functionName: "share",
|
|
2926
|
+
args: [toChainShare(acp)],
|
|
2927
|
+
account: walletClient.account,
|
|
2928
|
+
chain: walletClient.chain ?? null
|
|
2929
|
+
});
|
|
2930
|
+
return { txHash, shareId: computeShareId(acp) };
|
|
2931
|
+
};
|
|
2932
|
+
var getIncomingShares = async (publicClient, registry, recipient) => {
|
|
2933
|
+
const raw = await publicClient.readContract({
|
|
2934
|
+
address: registry,
|
|
2935
|
+
abi: ACP_SHARE_REGISTRY_ABI,
|
|
2936
|
+
functionName: "sharesFor",
|
|
2937
|
+
args: [recipient]
|
|
2938
|
+
});
|
|
2939
|
+
return raw.map((s) => ({
|
|
2940
|
+
shareId: viem.keccak256(viem.encodeAbiParameters(ACP_TUPLE, [s])),
|
|
2941
|
+
issuer: s.issuer,
|
|
2942
|
+
expiration: Number(s.expiration),
|
|
2943
|
+
recipient: s.recipient,
|
|
2944
|
+
revokerData: Number(s.revokerData),
|
|
2945
|
+
revokerContract: s.revokerContract,
|
|
2946
|
+
scope: Number(s.scope),
|
|
2947
|
+
contracts: [...s.contracts],
|
|
2948
|
+
handles: [...s.handles],
|
|
2949
|
+
issuerSignature: s.issuerSignature
|
|
2950
|
+
}));
|
|
2951
|
+
};
|
|
2952
|
+
var importFromChain = async (share, publicClient, walletClient) => {
|
|
2953
|
+
const { shareId: _shareId, ...options } = share;
|
|
2954
|
+
return importShared({ ...options, type: "sharing" }, publicClient, walletClient);
|
|
2955
|
+
};
|
|
2956
|
+
var removeShareOnChain = async (shareId, walletClient, registry) => {
|
|
2957
|
+
if (walletClient.account == null)
|
|
2958
|
+
throw new Error("Missing walletClient account");
|
|
2959
|
+
return walletClient.writeContract({
|
|
2960
|
+
address: registry,
|
|
2961
|
+
abi: ACP_SHARE_REGISTRY_ABI,
|
|
2962
|
+
functionName: "removeShare",
|
|
2963
|
+
args: [shareId],
|
|
2964
|
+
account: walletClient.account,
|
|
2965
|
+
chain: walletClient.chain ?? null
|
|
2966
|
+
});
|
|
2967
|
+
};
|
|
2968
|
+
var removeACP2 = async (chainId, account, hash) => acpStore.removeACP(chainId, account, hash);
|
|
2969
|
+
var removeActiveACP = async (chainId, account) => acpStore.removeActiveACPHash(chainId, account);
|
|
2970
|
+
var acps = {
|
|
2971
|
+
getSnapshot: acpStore.store.getState,
|
|
2972
|
+
subscribe: acpStore.store.subscribe,
|
|
2774
2973
|
createSelf,
|
|
2775
2974
|
createSharing,
|
|
2776
2975
|
importShared,
|
|
2777
|
-
|
|
2778
|
-
|
|
2976
|
+
getOrCreateSelfACP,
|
|
2977
|
+
getOrCreateSharingACP,
|
|
2779
2978
|
getHash,
|
|
2780
2979
|
export: exportShared,
|
|
2781
2980
|
serialize,
|
|
2782
2981
|
deserialize,
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2982
|
+
getACP: getACP2,
|
|
2983
|
+
getACPs: getACPs2,
|
|
2984
|
+
getActiveACP: getActiveACP2,
|
|
2985
|
+
getActiveACPHash: getActiveACPHash2,
|
|
2986
|
+
removeACP: removeACP2,
|
|
2987
|
+
selectActiveACP,
|
|
2988
|
+
removeActiveACP,
|
|
2989
|
+
revokeACP,
|
|
2990
|
+
revokeAllACPs,
|
|
2991
|
+
isACPRevoked,
|
|
2992
|
+
shareOnChain,
|
|
2993
|
+
getIncomingShares,
|
|
2994
|
+
importFromChain,
|
|
2995
|
+
removeShareOnChain,
|
|
2996
|
+
computeShareId,
|
|
2997
|
+
applyACPDefaults,
|
|
2998
|
+
applyACPDefaultsFromChain,
|
|
2999
|
+
getAclServedAddresses,
|
|
3000
|
+
clearAclServedAddresses
|
|
2790
3001
|
};
|
|
2791
3002
|
function uint160ToAddress(uint160) {
|
|
2792
3003
|
const hexStr = uint160.toString(16).padStart(40, "0");
|
|
@@ -2849,13 +3060,16 @@ var MockThresholdNetworkAbi = [
|
|
|
2849
3060
|
{
|
|
2850
3061
|
name: "permission",
|
|
2851
3062
|
type: "tuple",
|
|
2852
|
-
internalType: "struct
|
|
3063
|
+
internalType: "struct ACPermission",
|
|
2853
3064
|
components: [
|
|
2854
3065
|
{ name: "issuer", type: "address", internalType: "address" },
|
|
2855
3066
|
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2856
3067
|
{ name: "recipient", type: "address", internalType: "address" },
|
|
2857
|
-
{ name: "
|
|
2858
|
-
{ name: "
|
|
3068
|
+
{ name: "revokerData", type: "uint256", internalType: "uint256" },
|
|
3069
|
+
{ name: "revokerContract", type: "address", internalType: "address" },
|
|
3070
|
+
{ name: "scope", type: "uint8", internalType: "uint8" },
|
|
3071
|
+
{ name: "contracts", type: "address[]", internalType: "address[]" },
|
|
3072
|
+
{ name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
|
|
2859
3073
|
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2860
3074
|
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2861
3075
|
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
@@ -2878,13 +3092,16 @@ var MockThresholdNetworkAbi = [
|
|
|
2878
3092
|
{
|
|
2879
3093
|
name: "permission",
|
|
2880
3094
|
type: "tuple",
|
|
2881
|
-
internalType: "struct
|
|
3095
|
+
internalType: "struct ACPermission",
|
|
2882
3096
|
components: [
|
|
2883
3097
|
{ name: "issuer", type: "address", internalType: "address" },
|
|
2884
3098
|
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2885
3099
|
{ name: "recipient", type: "address", internalType: "address" },
|
|
2886
|
-
{ name: "
|
|
2887
|
-
{ name: "
|
|
3100
|
+
{ name: "revokerData", type: "uint256", internalType: "uint256" },
|
|
3101
|
+
{ name: "revokerContract", type: "address", internalType: "address" },
|
|
3102
|
+
{ name: "scope", type: "uint8", internalType: "uint8" },
|
|
3103
|
+
{ name: "contracts", type: "address[]", internalType: "address[]" },
|
|
3104
|
+
{ name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
|
|
2888
3105
|
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2889
3106
|
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2890
3107
|
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
@@ -2949,19 +3166,22 @@ var MockThresholdNetworkAbi = [
|
|
|
2949
3166
|
},
|
|
2950
3167
|
{
|
|
2951
3168
|
type: "function",
|
|
2952
|
-
name: "
|
|
3169
|
+
name: "decryptForTxWithACP",
|
|
2953
3170
|
inputs: [
|
|
2954
3171
|
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
2955
3172
|
{
|
|
2956
3173
|
name: "permission",
|
|
2957
3174
|
type: "tuple",
|
|
2958
|
-
internalType: "struct
|
|
3175
|
+
internalType: "struct ACPermission",
|
|
2959
3176
|
components: [
|
|
2960
3177
|
{ name: "issuer", type: "address", internalType: "address" },
|
|
2961
3178
|
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2962
3179
|
{ name: "recipient", type: "address", internalType: "address" },
|
|
2963
|
-
{ name: "
|
|
2964
|
-
{ name: "
|
|
3180
|
+
{ name: "revokerData", type: "uint256", internalType: "uint256" },
|
|
3181
|
+
{ name: "revokerContract", type: "address", internalType: "address" },
|
|
3182
|
+
{ name: "scope", type: "uint8", internalType: "uint8" },
|
|
3183
|
+
{ name: "contracts", type: "address[]", internalType: "address[]" },
|
|
3184
|
+
{ name: "handles", type: "bytes32[]", internalType: "bytes32[]" },
|
|
2965
3185
|
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2966
3186
|
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2967
3187
|
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
@@ -2977,7 +3197,7 @@ var MockThresholdNetworkAbi = [
|
|
|
2977
3197
|
},
|
|
2978
3198
|
{
|
|
2979
3199
|
type: "function",
|
|
2980
|
-
name: "
|
|
3200
|
+
name: "decryptForTxWithoutACP",
|
|
2981
3201
|
inputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
|
|
2982
3202
|
outputs: [
|
|
2983
3203
|
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
@@ -2989,12 +3209,12 @@ var MockThresholdNetworkAbi = [
|
|
|
2989
3209
|
];
|
|
2990
3210
|
|
|
2991
3211
|
// core/decrypt/cofheMocksDecryptForView.ts
|
|
2992
|
-
async function cofheMocksDecryptForView(ctHash, utype,
|
|
2993
|
-
const
|
|
3212
|
+
async function cofheMocksDecryptForView(ctHash, utype, acp, publicClient) {
|
|
3213
|
+
const wireAcp = ACPUtils.getPublic(acp, true);
|
|
2994
3214
|
const permissionWithBigInts = {
|
|
2995
|
-
...
|
|
2996
|
-
expiration: BigInt(
|
|
2997
|
-
|
|
3215
|
+
...wireAcp,
|
|
3216
|
+
expiration: BigInt(wireAcp.expiration),
|
|
3217
|
+
revokerData: BigInt(wireAcp.revokerData)
|
|
2998
3218
|
};
|
|
2999
3219
|
const [allowed, error, result] = await publicClient.readContract({
|
|
3000
3220
|
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
@@ -3015,11 +3235,41 @@ async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
|
|
|
3015
3235
|
});
|
|
3016
3236
|
}
|
|
3017
3237
|
const sealedBigInt = BigInt(result);
|
|
3018
|
-
const sealingKeyBigInt = BigInt(
|
|
3238
|
+
const sealingKeyBigInt = BigInt(acp.sealingKey);
|
|
3019
3239
|
const unsealed = sealedBigInt ^ sealingKeyBigInt;
|
|
3020
3240
|
return unsealed;
|
|
3021
3241
|
}
|
|
3022
3242
|
|
|
3243
|
+
// core/debug.ts
|
|
3244
|
+
var interceptors = {};
|
|
3245
|
+
function setCofheDebugInterceptors(next) {
|
|
3246
|
+
interceptors.onRequest = next?.onRequest;
|
|
3247
|
+
interceptors.onResponse = next?.onResponse;
|
|
3248
|
+
}
|
|
3249
|
+
function getCofheDebugInterceptors() {
|
|
3250
|
+
return interceptors;
|
|
3251
|
+
}
|
|
3252
|
+
async function cofheFetch(url, init, ctx = { op: "request" }) {
|
|
3253
|
+
let finalUrl = url;
|
|
3254
|
+
let finalInit = init;
|
|
3255
|
+
if (interceptors.onRequest) {
|
|
3256
|
+
const override = await interceptors.onRequest(finalUrl, finalInit, ctx);
|
|
3257
|
+
if (override) {
|
|
3258
|
+
if (override.url !== void 0)
|
|
3259
|
+
finalUrl = override.url;
|
|
3260
|
+
if (override.init !== void 0)
|
|
3261
|
+
finalInit = override.init;
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
let response = await fetch(finalUrl, finalInit);
|
|
3265
|
+
if (interceptors.onResponse) {
|
|
3266
|
+
const replaced = await interceptors.onResponse(response, ctx);
|
|
3267
|
+
if (replaced)
|
|
3268
|
+
response = replaced;
|
|
3269
|
+
}
|
|
3270
|
+
return response;
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3023
3273
|
// core/decrypt/polling.ts
|
|
3024
3274
|
function computeMinuteRampPollIntervalMs(elapsedMs, params) {
|
|
3025
3275
|
const elapsedSeconds = Math.floor(elapsedMs / 1e3);
|
|
@@ -3028,11 +3278,61 @@ function computeMinuteRampPollIntervalMs(elapsedMs, params) {
|
|
|
3028
3278
|
return Math.min(params.maxIntervalMs, Math.max(params.minIntervalMs, intervalMs));
|
|
3029
3279
|
}
|
|
3030
3280
|
|
|
3281
|
+
// core/decrypt/apiError.ts
|
|
3282
|
+
var BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE = {
|
|
3283
|
+
bad_request: "BAD_REQUEST" /* BadRequest */,
|
|
3284
|
+
unknown_chain: "UNKNOWN_CHAIN" /* UnknownChain */,
|
|
3285
|
+
acp_malformed: "ACP_MALFORMED" /* ACPMalformed */,
|
|
3286
|
+
acp_denied: "ACP_DENIED" /* ACPDenied */,
|
|
3287
|
+
// ACP-era backends fold revoked into denied
|
|
3288
|
+
acp_expired: "ACP_EXPIRED" /* ACPExpired */,
|
|
3289
|
+
acp_invalid: "ACP_INVALID" /* ACPInvalid */,
|
|
3290
|
+
acp_required: "ACP_REQUIRED" /* ACPRequired */,
|
|
3291
|
+
acp_verifier_error: "ACP_VERIFIER_ERROR" /* ACPVerifierError */,
|
|
3292
|
+
acp_verifier_timeout: "ACP_VERIFIER_TIMEOUT" /* ACPVerifierTimeout */,
|
|
3293
|
+
not_publicly_allowed: "NOT_PUBLICLY_ALLOWED" /* NotPubliclyAllowed */,
|
|
3294
|
+
ct_not_found: "CT_NOT_FOUND" /* CtNotFound */,
|
|
3295
|
+
unsupported_security_zone: "UNSUPPORTED_SECURITY_ZONE" /* UnsupportedSecurityZone */,
|
|
3296
|
+
unsupported_type: "UNSUPPORTED_TYPE" /* UnsupportedType */,
|
|
3297
|
+
internal_error: "INTERNAL_ERROR" /* InternalError */,
|
|
3298
|
+
signing_failed: "SIGNING_FAILED" /* SigningFailed */,
|
|
3299
|
+
ct_source_error: "CT_SOURCE_ERROR" /* CtSourceError */,
|
|
3300
|
+
ct_source_timeout: "CT_SOURCE_TIMEOUT" /* CtSourceTimeout */,
|
|
3301
|
+
seal_failed: "SEAL_FAILED" /* SealFailed */
|
|
3302
|
+
};
|
|
3303
|
+
function isBackendApiErrorCode(value) {
|
|
3304
|
+
return value in BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE;
|
|
3305
|
+
}
|
|
3306
|
+
async function parseApiErrorResponseBody(response) {
|
|
3307
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
3308
|
+
let apiErrorCode;
|
|
3309
|
+
try {
|
|
3310
|
+
const body = await response.json();
|
|
3311
|
+
if (body && typeof body === "object") {
|
|
3312
|
+
const record = body;
|
|
3313
|
+
if (typeof record.error === "string" && record.error.length > 0) {
|
|
3314
|
+
apiErrorCode = record.error;
|
|
3315
|
+
}
|
|
3316
|
+
if (typeof record.error_message === "string" && record.error_message.length > 0) {
|
|
3317
|
+
errorMessage = record.error_message;
|
|
3318
|
+
} else if (typeof record.message === "string" && record.message.length > 0) {
|
|
3319
|
+
errorMessage = record.message;
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
} catch {
|
|
3323
|
+
errorMessage = response.statusText || errorMessage;
|
|
3324
|
+
}
|
|
3325
|
+
return { apiErrorCode, errorMessage };
|
|
3326
|
+
}
|
|
3327
|
+
function mapApiErrorCodeToCofheErrorCode(apiErrorCode, fallback) {
|
|
3328
|
+
if (apiErrorCode && isBackendApiErrorCode(apiErrorCode)) {
|
|
3329
|
+
return BACKEND_ERROR_CODE_TO_COFHE_ERROR_CODE[apiErrorCode];
|
|
3330
|
+
}
|
|
3331
|
+
return fallback;
|
|
3332
|
+
}
|
|
3333
|
+
|
|
3031
3334
|
// core/decrypt/submitRetry.ts
|
|
3032
3335
|
var DEFAULT_404_RETRY_TIMEOUT_MS = 1e4;
|
|
3033
|
-
function isRetryableSubmitStatus(status) {
|
|
3034
|
-
return status === 204 || status === 404;
|
|
3035
|
-
}
|
|
3036
3336
|
function normalize404RetryTimeoutMs(params) {
|
|
3037
3337
|
const { timeoutMs, operationLabel, errorCode } = params;
|
|
3038
3338
|
if (timeoutMs === void 0)
|
|
@@ -3049,32 +3349,24 @@ function normalize404RetryTimeoutMs(params) {
|
|
|
3049
3349
|
return timeoutMs;
|
|
3050
3350
|
}
|
|
3051
3351
|
async function classifySubmitResponse(params) {
|
|
3052
|
-
const { response,
|
|
3053
|
-
if (
|
|
3054
|
-
return { kind: "retryable", status:
|
|
3352
|
+
const { response, fallbackErrorCode } = params;
|
|
3353
|
+
if (response.status === 204) {
|
|
3354
|
+
return { kind: "retryable", status: 204 };
|
|
3055
3355
|
}
|
|
3056
3356
|
if (response.ok) {
|
|
3057
3357
|
return { kind: "parse-json" };
|
|
3058
3358
|
}
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
const maybeErrorMessage = extractErrorMessage?.(errorBody);
|
|
3063
|
-
if (typeof maybeErrorMessage === "string" && maybeErrorMessage.length > 0) {
|
|
3064
|
-
errorMessage = maybeErrorMessage;
|
|
3065
|
-
} else if (errorBody && typeof errorBody === "object") {
|
|
3066
|
-
const defaultMessage = errorBody.error_message;
|
|
3067
|
-
const fallbackMessage = errorBody.message;
|
|
3068
|
-
if (typeof defaultMessage === "string" && defaultMessage.length > 0) {
|
|
3069
|
-
errorMessage = defaultMessage;
|
|
3070
|
-
} else if (typeof fallbackMessage === "string" && fallbackMessage.length > 0) {
|
|
3071
|
-
errorMessage = fallbackMessage;
|
|
3072
|
-
}
|
|
3073
|
-
}
|
|
3074
|
-
} catch {
|
|
3075
|
-
errorMessage = response.statusText || errorMessage;
|
|
3359
|
+
const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
|
|
3360
|
+
if (response.status === 404) {
|
|
3361
|
+
return { kind: "retryable", status: 404, apiErrorMessage: errorMessage };
|
|
3076
3362
|
}
|
|
3077
|
-
return {
|
|
3363
|
+
return {
|
|
3364
|
+
kind: "fatal-http",
|
|
3365
|
+
status: response.status,
|
|
3366
|
+
cofheErrorCode: mapApiErrorCodeToCofheErrorCode(apiErrorCode, fallbackErrorCode),
|
|
3367
|
+
apiErrorCode,
|
|
3368
|
+
errorMessage
|
|
3369
|
+
};
|
|
3078
3370
|
}
|
|
3079
3371
|
function throwIfSubmitRetryTimedOut(params) {
|
|
3080
3372
|
const {
|
|
@@ -3086,12 +3378,14 @@ function throwIfSubmitRetryTimedOut(params) {
|
|
|
3086
3378
|
overallTimeoutMs,
|
|
3087
3379
|
thresholdNetworkUrl,
|
|
3088
3380
|
body,
|
|
3089
|
-
attemptIndex
|
|
3381
|
+
attemptIndex,
|
|
3382
|
+
lastKnownErrorMessage
|
|
3090
3383
|
} = params;
|
|
3091
3384
|
if (status === 404 && elapsedMs > retry404TimeoutMs) {
|
|
3092
3385
|
throw new CofheError({
|
|
3093
|
-
code:
|
|
3094
|
-
|
|
3386
|
+
code: "CT_NOT_FOUND" /* CtNotFound */,
|
|
3387
|
+
apiErrorCode: "ct_not_found",
|
|
3388
|
+
message: `${operationLabel} ciphertext not found after retrying for ${retry404TimeoutMs}ms` + (lastKnownErrorMessage ? `: ${lastKnownErrorMessage}` : ""),
|
|
3095
3389
|
hint: "The ciphertext may not be indexed yet. Increase set404RetryTimeout(...) if the backend is slow to index ciphertexts.",
|
|
3096
3390
|
context: {
|
|
3097
3391
|
thresholdNetworkUrl,
|
|
@@ -3117,6 +3411,62 @@ function throwIfSubmitRetryTimedOut(params) {
|
|
|
3117
3411
|
});
|
|
3118
3412
|
}
|
|
3119
3413
|
}
|
|
3414
|
+
function normalizeTnSignature(signature) {
|
|
3415
|
+
if (typeof signature !== "string") {
|
|
3416
|
+
throw new CofheError({
|
|
3417
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3418
|
+
message: "decrypt response missing signature",
|
|
3419
|
+
context: {
|
|
3420
|
+
signature
|
|
3421
|
+
}
|
|
3422
|
+
});
|
|
3423
|
+
}
|
|
3424
|
+
const trimmed = signature.trim();
|
|
3425
|
+
if (trimmed.length === 0) {
|
|
3426
|
+
throw new CofheError({
|
|
3427
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3428
|
+
message: "decrypt response returned empty signature"
|
|
3429
|
+
});
|
|
3430
|
+
}
|
|
3431
|
+
const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
|
|
3432
|
+
const parsed = viem.parseSignature(prefixed);
|
|
3433
|
+
return viem.serializeSignature(parsed);
|
|
3434
|
+
}
|
|
3435
|
+
function parseDecryptedBytesToBigInt(decrypted) {
|
|
3436
|
+
if (!Array.isArray(decrypted)) {
|
|
3437
|
+
throw new CofheError({
|
|
3438
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3439
|
+
message: "decrypt response field <decrypted> must be a byte array",
|
|
3440
|
+
context: {
|
|
3441
|
+
decrypted
|
|
3442
|
+
}
|
|
3443
|
+
});
|
|
3444
|
+
}
|
|
3445
|
+
if (decrypted.length === 0) {
|
|
3446
|
+
throw new CofheError({
|
|
3447
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3448
|
+
message: "decrypt response field <decrypted> was an empty byte array",
|
|
3449
|
+
context: {
|
|
3450
|
+
decrypted
|
|
3451
|
+
}
|
|
3452
|
+
});
|
|
3453
|
+
}
|
|
3454
|
+
let hex = "";
|
|
3455
|
+
for (const b of decrypted) {
|
|
3456
|
+
if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
|
|
3457
|
+
throw new CofheError({
|
|
3458
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3459
|
+
message: "decrypt response field <decrypted> contained a non-byte value",
|
|
3460
|
+
context: {
|
|
3461
|
+
badElement: b,
|
|
3462
|
+
decrypted
|
|
3463
|
+
}
|
|
3464
|
+
});
|
|
3465
|
+
}
|
|
3466
|
+
hex += b.toString(16).padStart(2, "0");
|
|
3467
|
+
}
|
|
3468
|
+
return BigInt(`0x${hex}`);
|
|
3469
|
+
}
|
|
3120
3470
|
|
|
3121
3471
|
// core/decrypt/tnSealOutputV2.ts
|
|
3122
3472
|
var POLL_INTERVAL_MS = 1e3;
|
|
@@ -3179,23 +3529,28 @@ function parseCompletedSealOutputResponse(params) {
|
|
|
3179
3529
|
}
|
|
3180
3530
|
return convertSealedData(sealed);
|
|
3181
3531
|
}
|
|
3182
|
-
async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId,
|
|
3532
|
+
async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, acp, overallStartTime, retry404TimeoutMs, onPoll) {
|
|
3183
3533
|
const body = {
|
|
3184
3534
|
ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
|
|
3185
3535
|
host_chain_id: chainId,
|
|
3186
|
-
|
|
3536
|
+
acp
|
|
3187
3537
|
};
|
|
3188
3538
|
let attemptIndex = 0;
|
|
3539
|
+
let last404ApiErrorMessage;
|
|
3189
3540
|
for (; ; ) {
|
|
3190
3541
|
let response;
|
|
3191
3542
|
try {
|
|
3192
|
-
response = await
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3543
|
+
response = await cofheFetch(
|
|
3544
|
+
`${thresholdNetworkUrl}/v2/sealoutput`,
|
|
3545
|
+
/*op:sealoutput*/
|
|
3546
|
+
{
|
|
3547
|
+
method: "POST",
|
|
3548
|
+
headers: {
|
|
3549
|
+
"Content-Type": "application/json"
|
|
3550
|
+
},
|
|
3551
|
+
body: JSON.stringify(body)
|
|
3552
|
+
}
|
|
3553
|
+
);
|
|
3199
3554
|
} catch (e) {
|
|
3200
3555
|
throw new CofheError({
|
|
3201
3556
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
@@ -3209,16 +3564,19 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
3209
3564
|
}
|
|
3210
3565
|
});
|
|
3211
3566
|
}
|
|
3212
|
-
const responseClassification = await classifySubmitResponse({
|
|
3567
|
+
const responseClassification = await classifySubmitResponse({
|
|
3568
|
+
response,
|
|
3569
|
+
fallbackErrorCode: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */
|
|
3570
|
+
});
|
|
3213
3571
|
if (responseClassification.kind === "fatal-http") {
|
|
3214
3572
|
throw new CofheError({
|
|
3215
|
-
code:
|
|
3573
|
+
code: responseClassification.cofheErrorCode,
|
|
3574
|
+
apiErrorCode: responseClassification.apiErrorCode,
|
|
3216
3575
|
message: `sealOutput request failed: ${responseClassification.errorMessage}`,
|
|
3217
3576
|
hint: "Check the threshold network URL and request parameters.",
|
|
3218
3577
|
context: {
|
|
3219
3578
|
thresholdNetworkUrl,
|
|
3220
|
-
status:
|
|
3221
|
-
statusText: response.statusText,
|
|
3579
|
+
status: responseClassification.status,
|
|
3222
3580
|
body,
|
|
3223
3581
|
attemptIndex
|
|
3224
3582
|
}
|
|
@@ -3264,6 +3622,9 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
3264
3622
|
}
|
|
3265
3623
|
});
|
|
3266
3624
|
}
|
|
3625
|
+
if (responseClassification.status === 404) {
|
|
3626
|
+
last404ApiErrorMessage = responseClassification.apiErrorMessage;
|
|
3627
|
+
}
|
|
3267
3628
|
const elapsedMs = Date.now() - overallStartTime;
|
|
3268
3629
|
throwIfSubmitRetryTimedOut({
|
|
3269
3630
|
operationLabel: "sealOutput",
|
|
@@ -3274,7 +3635,8 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
3274
3635
|
overallTimeoutMs: SEAL_OUTPUT_TIMEOUT_MS,
|
|
3275
3636
|
thresholdNetworkUrl,
|
|
3276
3637
|
body,
|
|
3277
|
-
attemptIndex
|
|
3638
|
+
attemptIndex,
|
|
3639
|
+
lastKnownErrorMessage: last404ApiErrorMessage
|
|
3278
3640
|
});
|
|
3279
3641
|
onPoll?.({
|
|
3280
3642
|
operation: "sealoutput",
|
|
@@ -3318,12 +3680,16 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
|
|
|
3318
3680
|
}
|
|
3319
3681
|
let response;
|
|
3320
3682
|
try {
|
|
3321
|
-
response = await
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3683
|
+
response = await cofheFetch(
|
|
3684
|
+
`${thresholdNetworkUrl}/v2/sealoutput/${requestId}`,
|
|
3685
|
+
/*op:sealoutput-poll*/
|
|
3686
|
+
{
|
|
3687
|
+
method: "GET",
|
|
3688
|
+
headers: {
|
|
3689
|
+
"Content-Type": "application/json"
|
|
3690
|
+
}
|
|
3325
3691
|
}
|
|
3326
|
-
|
|
3692
|
+
);
|
|
3327
3693
|
} catch (e) {
|
|
3328
3694
|
throw new CofheError({
|
|
3329
3695
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
@@ -3348,15 +3714,10 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
|
|
|
3348
3714
|
});
|
|
3349
3715
|
}
|
|
3350
3716
|
if (!response.ok) {
|
|
3351
|
-
|
|
3352
|
-
try {
|
|
3353
|
-
const errorBody = await response.json();
|
|
3354
|
-
errorMessage = errorBody.error_message || errorBody.message || errorMessage;
|
|
3355
|
-
} catch {
|
|
3356
|
-
errorMessage = response.statusText || errorMessage;
|
|
3357
|
-
}
|
|
3717
|
+
const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
|
|
3358
3718
|
throw new CofheError({
|
|
3359
|
-
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed
|
|
3719
|
+
code: mapApiErrorCodeToCofheErrorCode(apiErrorCode, "SEAL_OUTPUT_FAILED" /* SealOutputFailed */),
|
|
3720
|
+
apiErrorCode,
|
|
3360
3721
|
message: `sealOutput status poll failed: ${errorMessage}`,
|
|
3361
3722
|
context: {
|
|
3362
3723
|
thresholdNetworkUrl,
|
|
@@ -3400,7 +3761,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStart
|
|
|
3400
3761
|
});
|
|
3401
3762
|
}
|
|
3402
3763
|
async function tnSealOutputV2(params) {
|
|
3403
|
-
const { thresholdNetworkUrl, ctHash, chainId,
|
|
3764
|
+
const { thresholdNetworkUrl, ctHash, chainId, acp, retry404TimeoutMs, onPoll } = params;
|
|
3404
3765
|
const normalized404RetryTimeoutMs = normalize404RetryTimeoutMs({
|
|
3405
3766
|
timeoutMs: retry404TimeoutMs,
|
|
3406
3767
|
operationLabel: "sealOutput",
|
|
@@ -3411,7 +3772,7 @@ async function tnSealOutputV2(params) {
|
|
|
3411
3772
|
thresholdNetworkUrl,
|
|
3412
3773
|
ctHash,
|
|
3413
3774
|
chainId,
|
|
3414
|
-
|
|
3775
|
+
acp,
|
|
3415
3776
|
overallStartTime,
|
|
3416
3777
|
normalized404RetryTimeoutMs,
|
|
3417
3778
|
onPoll
|
|
@@ -3427,8 +3788,8 @@ var DEFAULT_404_RETRY_TIMEOUT_MS2 = 1e4;
|
|
|
3427
3788
|
var DecryptForViewBuilder = class extends BaseBuilder {
|
|
3428
3789
|
ctHash;
|
|
3429
3790
|
utype;
|
|
3430
|
-
|
|
3431
|
-
|
|
3791
|
+
acpHash;
|
|
3792
|
+
acp;
|
|
3432
3793
|
pollCallback;
|
|
3433
3794
|
retry404TimeoutMs = DEFAULT_404_RETRY_TIMEOUT_MS2;
|
|
3434
3795
|
constructor(params) {
|
|
@@ -3442,11 +3803,11 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3442
3803
|
});
|
|
3443
3804
|
this.ctHash = params.ctHash;
|
|
3444
3805
|
this.utype = params.utype;
|
|
3445
|
-
this.
|
|
3446
|
-
this.
|
|
3806
|
+
this.acpHash = params.acpHash;
|
|
3807
|
+
this.acp = params.acp;
|
|
3447
3808
|
}
|
|
3448
3809
|
/**
|
|
3449
|
-
* @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct
|
|
3810
|
+
* @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct acp.
|
|
3450
3811
|
*
|
|
3451
3812
|
* If not provided, the chainId will be fetched from the connected publicClient.
|
|
3452
3813
|
*
|
|
@@ -3467,7 +3828,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3467
3828
|
return this.chainId;
|
|
3468
3829
|
}
|
|
3469
3830
|
/**
|
|
3470
|
-
* @param account - Account to decrypt values from. Used to fetch the correct
|
|
3831
|
+
* @param account - Account to decrypt values from. Used to fetch the correct acp.
|
|
3471
3832
|
*
|
|
3472
3833
|
* If not provided, the account will be fetched from the connected walletClient.
|
|
3473
3834
|
*
|
|
@@ -3504,61 +3865,61 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3504
3865
|
this.retry404TimeoutMs = timeoutMs;
|
|
3505
3866
|
return this;
|
|
3506
3867
|
}
|
|
3507
|
-
|
|
3508
|
-
if (typeof
|
|
3509
|
-
this.
|
|
3510
|
-
this.
|
|
3511
|
-
} else if (
|
|
3512
|
-
this.
|
|
3513
|
-
this.
|
|
3868
|
+
withACP(acpOrACPHash) {
|
|
3869
|
+
if (typeof acpOrACPHash === "string") {
|
|
3870
|
+
this.acpHash = acpOrACPHash;
|
|
3871
|
+
this.acp = void 0;
|
|
3872
|
+
} else if (acpOrACPHash === void 0) {
|
|
3873
|
+
this.acpHash = void 0;
|
|
3874
|
+
this.acp = void 0;
|
|
3514
3875
|
} else {
|
|
3515
|
-
this.
|
|
3516
|
-
this.
|
|
3876
|
+
this.acp = acpOrACPHash;
|
|
3877
|
+
this.acpHash = void 0;
|
|
3517
3878
|
}
|
|
3518
3879
|
return this;
|
|
3519
3880
|
}
|
|
3520
3881
|
/**
|
|
3521
|
-
* @param
|
|
3882
|
+
* @param acpHash - ACP hash to decrypt values from. Used to fetch the correct acp.
|
|
3522
3883
|
*
|
|
3523
|
-
* If not provided, the active
|
|
3524
|
-
* If `
|
|
3884
|
+
* If not provided, the active acp for the chainId and account will be used.
|
|
3885
|
+
* If `setACP()` is called, it will be used regardless of chainId, account, or acpHash.
|
|
3525
3886
|
*
|
|
3526
3887
|
* Example:
|
|
3527
3888
|
* ```typescript
|
|
3528
3889
|
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
3529
|
-
* .
|
|
3890
|
+
* .setACPHash('0x1234567890123456789012345678901234567890')
|
|
3530
3891
|
* .execute();
|
|
3531
3892
|
* ```
|
|
3532
3893
|
*
|
|
3533
3894
|
* @returns The chainable DecryptForViewBuilder instance.
|
|
3534
3895
|
*/
|
|
3535
|
-
/** @deprecated Use `
|
|
3536
|
-
|
|
3537
|
-
return this.
|
|
3896
|
+
/** @deprecated Use `withACP(acpHash)` instead. */
|
|
3897
|
+
setACPHash(acpHash) {
|
|
3898
|
+
return this.withACP(acpHash);
|
|
3538
3899
|
}
|
|
3539
|
-
|
|
3540
|
-
return this.
|
|
3900
|
+
getACPHash() {
|
|
3901
|
+
return this.acpHash;
|
|
3541
3902
|
}
|
|
3542
3903
|
/**
|
|
3543
|
-
* @param
|
|
3904
|
+
* @param acp - ACP to decrypt values with. If provided, it will be used regardless of chainId, account, or acpHash.
|
|
3544
3905
|
*
|
|
3545
|
-
* If not provided, the
|
|
3906
|
+
* If not provided, the acp will be determined by chainId, account, and acpHash.
|
|
3546
3907
|
*
|
|
3547
3908
|
* Example:
|
|
3548
3909
|
* ```typescript
|
|
3549
3910
|
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
3550
|
-
* .
|
|
3911
|
+
* .setACP(acp)
|
|
3551
3912
|
* .execute();
|
|
3552
3913
|
* ```
|
|
3553
3914
|
*
|
|
3554
3915
|
* @returns The chainable DecryptForViewBuilder instance.
|
|
3555
3916
|
*/
|
|
3556
|
-
/** @deprecated Use `
|
|
3557
|
-
|
|
3558
|
-
return this.
|
|
3917
|
+
/** @deprecated Use `withACP(acp)` instead. */
|
|
3918
|
+
setACP(acp) {
|
|
3919
|
+
return this.withACP(acp);
|
|
3559
3920
|
}
|
|
3560
|
-
|
|
3561
|
-
return this.
|
|
3921
|
+
getACP() {
|
|
3922
|
+
return this.acp;
|
|
3562
3923
|
}
|
|
3563
3924
|
async getThresholdNetworkUrl() {
|
|
3564
3925
|
this.assertChainId();
|
|
@@ -3574,77 +3935,77 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3574
3935
|
}
|
|
3575
3936
|
});
|
|
3576
3937
|
}
|
|
3577
|
-
async
|
|
3578
|
-
if (this.
|
|
3579
|
-
return this.
|
|
3938
|
+
async getResolvedACP() {
|
|
3939
|
+
if (this.acp)
|
|
3940
|
+
return this.acp;
|
|
3580
3941
|
this.assertChainId();
|
|
3581
3942
|
this.assertAccount();
|
|
3582
|
-
if (this.
|
|
3583
|
-
const
|
|
3584
|
-
if (!
|
|
3943
|
+
if (this.acpHash) {
|
|
3944
|
+
const acp2 = await acps.getACP(this.chainId, this.account, this.acpHash);
|
|
3945
|
+
if (!acp2) {
|
|
3585
3946
|
throw new CofheError({
|
|
3586
|
-
code: "
|
|
3587
|
-
message: `
|
|
3588
|
-
hint: "Ensure the
|
|
3947
|
+
code: "ACP_NOT_FOUND" /* ACPNotFound */,
|
|
3948
|
+
message: `ACP with hash <${this.acpHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
|
|
3949
|
+
hint: "Ensure the acp exists and is valid.",
|
|
3589
3950
|
context: {
|
|
3590
3951
|
chainId: this.chainId,
|
|
3591
3952
|
account: this.account,
|
|
3592
|
-
|
|
3953
|
+
acpHash: this.acpHash
|
|
3593
3954
|
}
|
|
3594
3955
|
});
|
|
3595
3956
|
}
|
|
3596
|
-
return
|
|
3957
|
+
return acp2;
|
|
3597
3958
|
}
|
|
3598
|
-
const
|
|
3599
|
-
if (!
|
|
3959
|
+
const acp = await acps.getActiveACP(this.chainId, this.account);
|
|
3960
|
+
if (!acp) {
|
|
3600
3961
|
throw new CofheError({
|
|
3601
|
-
code: "
|
|
3602
|
-
message: `Active
|
|
3603
|
-
hint: "Ensure
|
|
3962
|
+
code: "ACP_NOT_FOUND" /* ACPNotFound */,
|
|
3963
|
+
message: `Active acp not found for chainId <${this.chainId}> and account <${this.account}>`,
|
|
3964
|
+
hint: "Ensure an ACP exists for this account on this chain.",
|
|
3604
3965
|
context: {
|
|
3605
3966
|
chainId: this.chainId,
|
|
3606
3967
|
account: this.account
|
|
3607
3968
|
}
|
|
3608
3969
|
});
|
|
3609
3970
|
}
|
|
3610
|
-
return
|
|
3971
|
+
return acp;
|
|
3611
3972
|
}
|
|
3612
3973
|
/**
|
|
3613
3974
|
* On hardhat, interact with MockZkVerifier contract instead of CoFHE
|
|
3614
3975
|
*/
|
|
3615
|
-
async mocksSealOutput(
|
|
3976
|
+
async mocksSealOutput(acp) {
|
|
3616
3977
|
this.assertPublicClient();
|
|
3617
3978
|
const mocksDecryptDelay = this.config.mocks.decryptDelay;
|
|
3618
3979
|
if (mocksDecryptDelay > 0)
|
|
3619
3980
|
await sleep(mocksDecryptDelay);
|
|
3620
|
-
return cofheMocksDecryptForView(this.ctHash, this.utype,
|
|
3981
|
+
return cofheMocksDecryptForView(this.ctHash, this.utype, acp, this.publicClient);
|
|
3621
3982
|
}
|
|
3622
3983
|
/**
|
|
3623
3984
|
* In the production context, perform a true decryption with the CoFHE coprocessor.
|
|
3624
3985
|
*/
|
|
3625
|
-
async productionSealOutput(
|
|
3986
|
+
async productionSealOutput(acp) {
|
|
3626
3987
|
this.assertChainId();
|
|
3627
3988
|
this.assertPublicClient();
|
|
3628
3989
|
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3629
|
-
const
|
|
3990
|
+
const wireAcp = ACPUtils.getPublic(acp, true);
|
|
3630
3991
|
const sealed = await tnSealOutputV2({
|
|
3631
3992
|
ctHash: this.ctHash,
|
|
3632
3993
|
chainId: this.chainId,
|
|
3633
|
-
|
|
3994
|
+
acp: wireAcp,
|
|
3634
3995
|
thresholdNetworkUrl,
|
|
3635
3996
|
retry404TimeoutMs: this.retry404TimeoutMs,
|
|
3636
3997
|
onPoll: this.pollCallback
|
|
3637
3998
|
});
|
|
3638
|
-
return
|
|
3999
|
+
return ACPUtils.unseal(acp, sealed);
|
|
3639
4000
|
}
|
|
3640
4001
|
/**
|
|
3641
4002
|
* Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
|
|
3642
4003
|
*
|
|
3643
4004
|
* This will:
|
|
3644
|
-
* - Use
|
|
3645
|
-
* - Check
|
|
3646
|
-
* - Call CoFHE `/sealoutput` with the
|
|
3647
|
-
* - Unseal the sealed item with the
|
|
4005
|
+
* - Use an ACP based on provided acp OR chainId + account + acpHash
|
|
4006
|
+
* - Check acp validity
|
|
4007
|
+
* - Call CoFHE `/sealoutput` with the acp, which returns a sealed (encrypted) item
|
|
4008
|
+
* - Unseal the sealed item with the acp
|
|
3648
4009
|
* - Return the unsealed item
|
|
3649
4010
|
*
|
|
3650
4011
|
* Example:
|
|
@@ -3652,7 +4013,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3652
4013
|
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
3653
4014
|
* .setChainId(11155111) // optional
|
|
3654
4015
|
* .setAccount('0x123...890') // optional
|
|
3655
|
-
* .
|
|
4016
|
+
* .withACP() // optional
|
|
3656
4017
|
* .execute(); // execute
|
|
3657
4018
|
* ```
|
|
3658
4019
|
*
|
|
@@ -3660,14 +4021,14 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3660
4021
|
*/
|
|
3661
4022
|
async execute() {
|
|
3662
4023
|
this.validateUtypeOrThrow();
|
|
3663
|
-
const
|
|
3664
|
-
|
|
3665
|
-
const chainId =
|
|
4024
|
+
const acp = await this.getResolvedACP();
|
|
4025
|
+
ACPUtils.validate(acp);
|
|
4026
|
+
const chainId = acp._signedDomain.chainId;
|
|
3666
4027
|
let unsealed;
|
|
3667
4028
|
if (chainId === hardhat2.id) {
|
|
3668
|
-
unsealed = await this.mocksSealOutput(
|
|
4029
|
+
unsealed = await this.mocksSealOutput(acp);
|
|
3669
4030
|
} else {
|
|
3670
|
-
unsealed = await this.productionSealOutput(
|
|
4031
|
+
unsealed = await this.productionSealOutput(acp);
|
|
3671
4032
|
}
|
|
3672
4033
|
return convertViaUtype(this.utype, unsealed);
|
|
3673
4034
|
}
|
|
@@ -3675,28 +4036,28 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3675
4036
|
var UINT_TYPE_MASK = 0x7fn;
|
|
3676
4037
|
var TYPE_BYTE_OFFSET = 8n;
|
|
3677
4038
|
var getEncryptionTypeFromCtHash = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET & UINT_TYPE_MASK);
|
|
3678
|
-
async function cofheMocksDecryptForTx(ctHash, utype,
|
|
4039
|
+
async function cofheMocksDecryptForTx(ctHash, utype, acp, publicClient) {
|
|
3679
4040
|
let allowed;
|
|
3680
4041
|
let error;
|
|
3681
4042
|
let decryptedValue;
|
|
3682
|
-
if (
|
|
3683
|
-
|
|
4043
|
+
if (acp !== null) {
|
|
4044
|
+
const wireAcp = ACPUtils.getPublic(acp, true);
|
|
3684
4045
|
const permissionWithBigInts = {
|
|
3685
|
-
...
|
|
3686
|
-
expiration: BigInt(
|
|
3687
|
-
|
|
4046
|
+
...wireAcp,
|
|
4047
|
+
expiration: BigInt(wireAcp.expiration),
|
|
4048
|
+
revokerData: BigInt(wireAcp.revokerData)
|
|
3688
4049
|
};
|
|
3689
4050
|
[allowed, error, decryptedValue] = await publicClient.readContract({
|
|
3690
4051
|
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
3691
4052
|
abi: MockThresholdNetworkAbi,
|
|
3692
|
-
functionName: "
|
|
4053
|
+
functionName: "decryptForTxWithACP",
|
|
3693
4054
|
args: [BigInt(ctHash), permissionWithBigInts]
|
|
3694
4055
|
});
|
|
3695
4056
|
} else {
|
|
3696
4057
|
[allowed, error, decryptedValue] = await publicClient.readContract({
|
|
3697
4058
|
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
3698
4059
|
abi: MockThresholdNetworkAbi,
|
|
3699
|
-
functionName: "
|
|
4060
|
+
functionName: "decryptForTxWithoutACP",
|
|
3700
4061
|
args: [BigInt(ctHash)]
|
|
3701
4062
|
});
|
|
3702
4063
|
}
|
|
@@ -3731,62 +4092,6 @@ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
|
|
|
3731
4092
|
signature
|
|
3732
4093
|
};
|
|
3733
4094
|
}
|
|
3734
|
-
function normalizeTnSignature(signature) {
|
|
3735
|
-
if (typeof signature !== "string") {
|
|
3736
|
-
throw new CofheError({
|
|
3737
|
-
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3738
|
-
message: "decrypt response missing signature",
|
|
3739
|
-
context: {
|
|
3740
|
-
signature
|
|
3741
|
-
}
|
|
3742
|
-
});
|
|
3743
|
-
}
|
|
3744
|
-
const trimmed = signature.trim();
|
|
3745
|
-
if (trimmed.length === 0) {
|
|
3746
|
-
throw new CofheError({
|
|
3747
|
-
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3748
|
-
message: "decrypt response returned empty signature"
|
|
3749
|
-
});
|
|
3750
|
-
}
|
|
3751
|
-
const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
|
|
3752
|
-
const parsed = viem.parseSignature(prefixed);
|
|
3753
|
-
return viem.serializeSignature(parsed);
|
|
3754
|
-
}
|
|
3755
|
-
function parseDecryptedBytesToBigInt(decrypted) {
|
|
3756
|
-
if (!Array.isArray(decrypted)) {
|
|
3757
|
-
throw new CofheError({
|
|
3758
|
-
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3759
|
-
message: "decrypt response field <decrypted> must be a byte array",
|
|
3760
|
-
context: {
|
|
3761
|
-
decrypted
|
|
3762
|
-
}
|
|
3763
|
-
});
|
|
3764
|
-
}
|
|
3765
|
-
if (decrypted.length === 0) {
|
|
3766
|
-
throw new CofheError({
|
|
3767
|
-
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3768
|
-
message: "decrypt response field <decrypted> was an empty byte array",
|
|
3769
|
-
context: {
|
|
3770
|
-
decrypted
|
|
3771
|
-
}
|
|
3772
|
-
});
|
|
3773
|
-
}
|
|
3774
|
-
let hex = "";
|
|
3775
|
-
for (const b of decrypted) {
|
|
3776
|
-
if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
|
|
3777
|
-
throw new CofheError({
|
|
3778
|
-
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3779
|
-
message: "decrypt response field <decrypted> contained a non-byte value",
|
|
3780
|
-
context: {
|
|
3781
|
-
badElement: b,
|
|
3782
|
-
decrypted
|
|
3783
|
-
}
|
|
3784
|
-
});
|
|
3785
|
-
}
|
|
3786
|
-
hex += b.toString(16).padStart(2, "0");
|
|
3787
|
-
}
|
|
3788
|
-
return BigInt(`0x${hex}`);
|
|
3789
|
-
}
|
|
3790
4095
|
|
|
3791
4096
|
// core/decrypt/tnDecryptV2.ts
|
|
3792
4097
|
var POLL_INTERVAL_MS2 = 1e3;
|
|
@@ -3908,25 +4213,30 @@ function assertDecryptStatusResponseV2(value) {
|
|
|
3908
4213
|
}
|
|
3909
4214
|
return value;
|
|
3910
4215
|
}
|
|
3911
|
-
async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId,
|
|
4216
|
+
async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, acp, overallStartTime, retry404TimeoutMs, onPoll) {
|
|
3912
4217
|
const body = {
|
|
3913
4218
|
ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
|
|
3914
4219
|
host_chain_id: chainId
|
|
3915
4220
|
};
|
|
3916
|
-
if (
|
|
3917
|
-
body.
|
|
4221
|
+
if (acp) {
|
|
4222
|
+
body.acp = acp;
|
|
3918
4223
|
}
|
|
3919
4224
|
let attemptIndex = 0;
|
|
4225
|
+
let last404ApiErrorMessage;
|
|
3920
4226
|
for (; ; ) {
|
|
3921
4227
|
let response;
|
|
3922
4228
|
try {
|
|
3923
|
-
response = await
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
4229
|
+
response = await cofheFetch(
|
|
4230
|
+
`${thresholdNetworkUrl}/v2/decrypt`,
|
|
4231
|
+
/*op:decrypt*/
|
|
4232
|
+
{
|
|
4233
|
+
method: "POST",
|
|
4234
|
+
headers: {
|
|
4235
|
+
"Content-Type": "application/json"
|
|
4236
|
+
},
|
|
4237
|
+
body: JSON.stringify(body)
|
|
4238
|
+
}
|
|
4239
|
+
);
|
|
3930
4240
|
} catch (e) {
|
|
3931
4241
|
throw new CofheError({
|
|
3932
4242
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
@@ -3940,16 +4250,19 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
|
|
|
3940
4250
|
}
|
|
3941
4251
|
});
|
|
3942
4252
|
}
|
|
3943
|
-
const responseClassification = await classifySubmitResponse({
|
|
4253
|
+
const responseClassification = await classifySubmitResponse({
|
|
4254
|
+
response,
|
|
4255
|
+
fallbackErrorCode: "DECRYPT_FAILED" /* DecryptFailed */
|
|
4256
|
+
});
|
|
3944
4257
|
if (responseClassification.kind === "fatal-http") {
|
|
3945
4258
|
throw new CofheError({
|
|
3946
|
-
code:
|
|
4259
|
+
code: responseClassification.cofheErrorCode,
|
|
4260
|
+
apiErrorCode: responseClassification.apiErrorCode,
|
|
3947
4261
|
message: `decrypt request failed: ${responseClassification.errorMessage}`,
|
|
3948
4262
|
hint: "Check the threshold network URL and request parameters.",
|
|
3949
4263
|
context: {
|
|
3950
4264
|
thresholdNetworkUrl,
|
|
3951
|
-
status:
|
|
3952
|
-
statusText: response.statusText,
|
|
4265
|
+
status: responseClassification.status,
|
|
3953
4266
|
body,
|
|
3954
4267
|
attemptIndex
|
|
3955
4268
|
}
|
|
@@ -3997,6 +4310,9 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
|
|
|
3997
4310
|
}
|
|
3998
4311
|
});
|
|
3999
4312
|
}
|
|
4313
|
+
if (responseClassification.status === 404) {
|
|
4314
|
+
last404ApiErrorMessage = responseClassification.apiErrorMessage;
|
|
4315
|
+
}
|
|
4000
4316
|
const elapsedMs = Date.now() - overallStartTime;
|
|
4001
4317
|
throwIfSubmitRetryTimedOut({
|
|
4002
4318
|
operationLabel: "decrypt",
|
|
@@ -4007,7 +4323,8 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
|
|
|
4007
4323
|
overallTimeoutMs: DECRYPT_TIMEOUT_MS,
|
|
4008
4324
|
thresholdNetworkUrl,
|
|
4009
4325
|
body,
|
|
4010
|
-
attemptIndex
|
|
4326
|
+
attemptIndex,
|
|
4327
|
+
lastKnownErrorMessage: last404ApiErrorMessage
|
|
4011
4328
|
});
|
|
4012
4329
|
onPoll?.({
|
|
4013
4330
|
operation: "decrypt",
|
|
@@ -4051,12 +4368,16 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
|
|
|
4051
4368
|
}
|
|
4052
4369
|
let response;
|
|
4053
4370
|
try {
|
|
4054
|
-
response = await
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4371
|
+
response = await cofheFetch(
|
|
4372
|
+
`${thresholdNetworkUrl}/v2/decrypt/${requestId}`,
|
|
4373
|
+
/*op:decrypt-poll*/
|
|
4374
|
+
{
|
|
4375
|
+
method: "GET",
|
|
4376
|
+
headers: {
|
|
4377
|
+
"Content-Type": "application/json"
|
|
4378
|
+
}
|
|
4058
4379
|
}
|
|
4059
|
-
|
|
4380
|
+
);
|
|
4060
4381
|
} catch (e) {
|
|
4061
4382
|
throw new CofheError({
|
|
4062
4383
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
@@ -4081,17 +4402,10 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
|
|
|
4081
4402
|
});
|
|
4082
4403
|
}
|
|
4083
4404
|
if (!response.ok) {
|
|
4084
|
-
|
|
4085
|
-
try {
|
|
4086
|
-
const errorBody = await response.json();
|
|
4087
|
-
const maybeMessage = errorBody.error_message || errorBody.message;
|
|
4088
|
-
if (typeof maybeMessage === "string" && maybeMessage.length > 0)
|
|
4089
|
-
errorMessage = maybeMessage;
|
|
4090
|
-
} catch {
|
|
4091
|
-
errorMessage = response.statusText || errorMessage;
|
|
4092
|
-
}
|
|
4405
|
+
const { apiErrorCode, errorMessage } = await parseApiErrorResponseBody(response);
|
|
4093
4406
|
throw new CofheError({
|
|
4094
|
-
code: "DECRYPT_FAILED" /* DecryptFailed
|
|
4407
|
+
code: mapApiErrorCodeToCofheErrorCode(apiErrorCode, "DECRYPT_FAILED" /* DecryptFailed */),
|
|
4408
|
+
apiErrorCode,
|
|
4095
4409
|
message: `decrypt status poll failed: ${errorMessage}`,
|
|
4096
4410
|
context: {
|
|
4097
4411
|
thresholdNetworkUrl,
|
|
@@ -4136,7 +4450,7 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartT
|
|
|
4136
4450
|
});
|
|
4137
4451
|
}
|
|
4138
4452
|
async function tnDecryptV2(params) {
|
|
4139
|
-
const { thresholdNetworkUrl, ctHash, chainId,
|
|
4453
|
+
const { thresholdNetworkUrl, ctHash, chainId, acp, retry404TimeoutMs, onPoll } = params;
|
|
4140
4454
|
const normalized404RetryTimeoutMs = normalize404RetryTimeoutMs({
|
|
4141
4455
|
timeoutMs: retry404TimeoutMs,
|
|
4142
4456
|
operationLabel: "decrypt",
|
|
@@ -4147,7 +4461,7 @@ async function tnDecryptV2(params) {
|
|
|
4147
4461
|
thresholdNetworkUrl,
|
|
4148
4462
|
ctHash,
|
|
4149
4463
|
chainId,
|
|
4150
|
-
|
|
4464
|
+
acp,
|
|
4151
4465
|
overallStartTime,
|
|
4152
4466
|
normalized404RetryTimeoutMs,
|
|
4153
4467
|
onPoll
|
|
@@ -4162,9 +4476,9 @@ async function tnDecryptV2(params) {
|
|
|
4162
4476
|
var DEFAULT_404_RETRY_TIMEOUT_MS3 = 1e4;
|
|
4163
4477
|
var DecryptForTxBuilder = class extends BaseBuilder {
|
|
4164
4478
|
ctHash;
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4479
|
+
acpHash;
|
|
4480
|
+
acp;
|
|
4481
|
+
acpSelection = "unset";
|
|
4168
4482
|
pollCallback;
|
|
4169
4483
|
retry404TimeoutMs = DEFAULT_404_RETRY_TIMEOUT_MS3;
|
|
4170
4484
|
constructor(params) {
|
|
@@ -4209,137 +4523,137 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
4209
4523
|
this.retry404TimeoutMs = timeoutMs;
|
|
4210
4524
|
return this;
|
|
4211
4525
|
}
|
|
4212
|
-
|
|
4213
|
-
if (this.
|
|
4526
|
+
withACP(acpOrACPHash) {
|
|
4527
|
+
if (this.acpSelection === "with-acp") {
|
|
4214
4528
|
throw new CofheError({
|
|
4215
4529
|
code: "INTERNAL_ERROR" /* InternalError */,
|
|
4216
|
-
message: "decryptForTx:
|
|
4217
|
-
hint: "Choose the
|
|
4530
|
+
message: "decryptForTx: withACP() can only be selected once.",
|
|
4531
|
+
hint: "Choose the acp mode once. If you need a different acp, start a new decryptForTx() builder chain."
|
|
4218
4532
|
});
|
|
4219
4533
|
}
|
|
4220
|
-
if (this.
|
|
4534
|
+
if (this.acpSelection === "without-acp") {
|
|
4221
4535
|
throw new CofheError({
|
|
4222
4536
|
code: "INTERNAL_ERROR" /* InternalError */,
|
|
4223
|
-
message: "decryptForTx: cannot call
|
|
4224
|
-
hint: "Choose exactly one
|
|
4537
|
+
message: "decryptForTx: cannot call withACP() after withoutACP() has been selected.",
|
|
4538
|
+
hint: "Choose exactly one acp mode: either call .withACP(...) or .withoutACP(), but not both."
|
|
4225
4539
|
});
|
|
4226
4540
|
}
|
|
4227
|
-
this.
|
|
4228
|
-
if (typeof
|
|
4229
|
-
this.
|
|
4230
|
-
this.
|
|
4231
|
-
} else if (
|
|
4232
|
-
this.
|
|
4233
|
-
this.
|
|
4541
|
+
this.acpSelection = "with-acp";
|
|
4542
|
+
if (typeof acpOrACPHash === "string") {
|
|
4543
|
+
this.acpHash = acpOrACPHash;
|
|
4544
|
+
this.acp = void 0;
|
|
4545
|
+
} else if (acpOrACPHash === void 0) {
|
|
4546
|
+
this.acpHash = void 0;
|
|
4547
|
+
this.acp = void 0;
|
|
4234
4548
|
} else {
|
|
4235
|
-
this.
|
|
4236
|
-
this.
|
|
4549
|
+
this.acp = acpOrACPHash;
|
|
4550
|
+
this.acpHash = void 0;
|
|
4237
4551
|
}
|
|
4238
4552
|
return this;
|
|
4239
4553
|
}
|
|
4240
4554
|
/**
|
|
4241
|
-
* Select "no
|
|
4555
|
+
* Select "no acp" mode.
|
|
4242
4556
|
*
|
|
4243
|
-
* This uses global allowance (no
|
|
4557
|
+
* This uses global allowance (no acp required) and sends an empty permission payload to `/decrypt`.
|
|
4244
4558
|
*/
|
|
4245
|
-
|
|
4246
|
-
if (this.
|
|
4559
|
+
withoutACP() {
|
|
4560
|
+
if (this.acpSelection === "without-acp") {
|
|
4247
4561
|
throw new CofheError({
|
|
4248
4562
|
code: "INTERNAL_ERROR" /* InternalError */,
|
|
4249
|
-
message: "decryptForTx:
|
|
4250
|
-
hint: "Choose the
|
|
4563
|
+
message: "decryptForTx: withoutACP() can only be selected once.",
|
|
4564
|
+
hint: "Choose the acp mode once. If you need a different mode, start a new decryptForTx() builder chain."
|
|
4251
4565
|
});
|
|
4252
4566
|
}
|
|
4253
|
-
if (this.
|
|
4567
|
+
if (this.acpSelection === "with-acp") {
|
|
4254
4568
|
throw new CofheError({
|
|
4255
4569
|
code: "INTERNAL_ERROR" /* InternalError */,
|
|
4256
|
-
message: "decryptForTx: cannot call
|
|
4257
|
-
hint: "Choose exactly one
|
|
4570
|
+
message: "decryptForTx: cannot call withoutACP() after withACP() has been selected.",
|
|
4571
|
+
hint: "Choose exactly one acp mode: either call .withACP(...) or .withoutACP(), but not both."
|
|
4258
4572
|
});
|
|
4259
4573
|
}
|
|
4260
|
-
this.
|
|
4261
|
-
this.
|
|
4262
|
-
this.
|
|
4574
|
+
this.acpSelection = "without-acp";
|
|
4575
|
+
this.acpHash = void 0;
|
|
4576
|
+
this.acp = void 0;
|
|
4263
4577
|
return this;
|
|
4264
4578
|
}
|
|
4265
|
-
|
|
4266
|
-
return this.
|
|
4579
|
+
getACP() {
|
|
4580
|
+
return this.acp;
|
|
4267
4581
|
}
|
|
4268
|
-
|
|
4269
|
-
return this.
|
|
4582
|
+
getACPHash() {
|
|
4583
|
+
return this.acpHash;
|
|
4270
4584
|
}
|
|
4271
4585
|
async getThresholdNetworkUrl() {
|
|
4272
4586
|
this.assertChainId();
|
|
4273
4587
|
return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
|
|
4274
4588
|
}
|
|
4275
|
-
async
|
|
4276
|
-
if (this.
|
|
4589
|
+
async getResolvedACP() {
|
|
4590
|
+
if (this.acpSelection === "unset") {
|
|
4277
4591
|
throw new CofheError({
|
|
4278
4592
|
code: "INTERNAL_ERROR" /* InternalError */,
|
|
4279
|
-
message: "decryptForTx: missing
|
|
4280
|
-
hint: "Call .
|
|
4593
|
+
message: "decryptForTx: missing acp selection; call withACP(...) or withoutACP() before execute().",
|
|
4594
|
+
hint: "Call .withACP() to use the active acp, or .withoutACP() for global allowance."
|
|
4281
4595
|
});
|
|
4282
4596
|
}
|
|
4283
|
-
if (this.
|
|
4597
|
+
if (this.acpSelection === "without-acp") {
|
|
4284
4598
|
return null;
|
|
4285
4599
|
}
|
|
4286
|
-
if (this.
|
|
4287
|
-
return this.
|
|
4600
|
+
if (this.acp)
|
|
4601
|
+
return this.acp;
|
|
4288
4602
|
this.assertChainId();
|
|
4289
4603
|
this.assertAccount();
|
|
4290
|
-
if (this.
|
|
4291
|
-
const
|
|
4292
|
-
if (!
|
|
4604
|
+
if (this.acpHash) {
|
|
4605
|
+
const acp2 = await acps.getACP(this.chainId, this.account, this.acpHash);
|
|
4606
|
+
if (!acp2) {
|
|
4293
4607
|
throw new CofheError({
|
|
4294
|
-
code: "
|
|
4295
|
-
message: `
|
|
4296
|
-
hint: "Ensure the
|
|
4608
|
+
code: "ACP_NOT_FOUND" /* ACPNotFound */,
|
|
4609
|
+
message: `ACP with hash <${this.acpHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
|
|
4610
|
+
hint: "Ensure the acp exists and is valid.",
|
|
4297
4611
|
context: {
|
|
4298
4612
|
chainId: this.chainId,
|
|
4299
4613
|
account: this.account,
|
|
4300
|
-
|
|
4614
|
+
acpHash: this.acpHash
|
|
4301
4615
|
}
|
|
4302
4616
|
});
|
|
4303
4617
|
}
|
|
4304
|
-
return
|
|
4618
|
+
return acp2;
|
|
4305
4619
|
}
|
|
4306
|
-
const
|
|
4307
|
-
if (!
|
|
4620
|
+
const acp = await acps.getActiveACP(this.chainId, this.account);
|
|
4621
|
+
if (!acp) {
|
|
4308
4622
|
throw new CofheError({
|
|
4309
|
-
code: "
|
|
4310
|
-
message: `Active
|
|
4311
|
-
hint: "Create
|
|
4623
|
+
code: "ACP_NOT_FOUND" /* ACPNotFound */,
|
|
4624
|
+
message: `Active acp not found for chainId <${this.chainId}> and account <${this.account}>`,
|
|
4625
|
+
hint: "Create an ACP (e.g. client.acp.createSelf(...)) and/or set it active (client.acp.selectActiveACP(hash)).",
|
|
4312
4626
|
context: {
|
|
4313
4627
|
chainId: this.chainId,
|
|
4314
4628
|
account: this.account
|
|
4315
4629
|
}
|
|
4316
4630
|
});
|
|
4317
4631
|
}
|
|
4318
|
-
return
|
|
4632
|
+
return acp;
|
|
4319
4633
|
}
|
|
4320
4634
|
/**
|
|
4321
4635
|
* On hardhat, interact with MockThresholdNetwork contract
|
|
4322
4636
|
*/
|
|
4323
|
-
async mocksDecryptForTx(
|
|
4637
|
+
async mocksDecryptForTx(acp) {
|
|
4324
4638
|
this.assertPublicClient();
|
|
4325
4639
|
const delay = this.config.mocks.decryptDelay;
|
|
4326
4640
|
if (delay > 0)
|
|
4327
4641
|
await sleep(delay);
|
|
4328
|
-
const result = await cofheMocksDecryptForTx(this.ctHash, 0,
|
|
4642
|
+
const result = await cofheMocksDecryptForTx(this.ctHash, 0, acp, this.publicClient);
|
|
4329
4643
|
return result;
|
|
4330
4644
|
}
|
|
4331
4645
|
/**
|
|
4332
4646
|
* In the production context, perform a true decryption with the CoFHE coprocessor.
|
|
4333
4647
|
*/
|
|
4334
|
-
async productionDecryptForTx(
|
|
4648
|
+
async productionDecryptForTx(acp) {
|
|
4335
4649
|
this.assertChainId();
|
|
4336
4650
|
this.assertPublicClient();
|
|
4337
4651
|
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
4338
|
-
const
|
|
4652
|
+
const wireAcp = acp ? ACPUtils.getPublic(acp, true) : null;
|
|
4339
4653
|
const { decryptedValue, signature } = await tnDecryptV2({
|
|
4340
4654
|
ctHash: this.ctHash,
|
|
4341
4655
|
chainId: this.chainId,
|
|
4342
|
-
|
|
4656
|
+
acp: wireAcp,
|
|
4343
4657
|
thresholdNetworkUrl,
|
|
4344
4658
|
retry404TimeoutMs: this.retry404TimeoutMs,
|
|
4345
4659
|
onPoll: this.pollCallback
|
|
@@ -4353,19 +4667,19 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
4353
4667
|
/**
|
|
4354
4668
|
* Final step of the decryptForTx process. MUST BE CALLED LAST IN THE CHAIN.
|
|
4355
4669
|
*
|
|
4356
|
-
* You must explicitly choose one
|
|
4357
|
-
* - `
|
|
4358
|
-
* - `
|
|
4670
|
+
* You must explicitly choose one acp mode before calling `execute()`:
|
|
4671
|
+
* - `withACP(acp)` / `withACP(acpHash)` / `withACP()` (active acp)
|
|
4672
|
+
* - `withoutACP()` (global allowance)
|
|
4359
4673
|
*/
|
|
4360
4674
|
async execute() {
|
|
4361
|
-
const
|
|
4362
|
-
if (
|
|
4363
|
-
|
|
4364
|
-
const chainId =
|
|
4675
|
+
const acp = await this.getResolvedACP();
|
|
4676
|
+
if (acp !== null) {
|
|
4677
|
+
ACPUtils.validate(acp);
|
|
4678
|
+
const chainId = acp._signedDomain.chainId;
|
|
4365
4679
|
if (chainId === hardhat2.id) {
|
|
4366
|
-
return await this.mocksDecryptForTx(
|
|
4680
|
+
return await this.mocksDecryptForTx(acp);
|
|
4367
4681
|
} else {
|
|
4368
|
-
return await this.productionDecryptForTx(
|
|
4682
|
+
return await this.productionDecryptForTx(acp);
|
|
4369
4683
|
}
|
|
4370
4684
|
} else {
|
|
4371
4685
|
if (!this.chainId) {
|
|
@@ -4428,6 +4742,21 @@ function createCofheClientBase(opts) {
|
|
|
4428
4742
|
const updateConnectState = (partial) => {
|
|
4429
4743
|
connectStore.setState((state) => ({ ...state, ...partial }));
|
|
4430
4744
|
};
|
|
4745
|
+
const _resolveSharingRegistry = async (publicClient, chainId) => {
|
|
4746
|
+
const configured = opts.config.acp?.sharingRegistry?.[chainId];
|
|
4747
|
+
if (configured != null)
|
|
4748
|
+
return configured;
|
|
4749
|
+
const registry = (await acps.getAclServedAddresses(publicClient, chainId)).shareRegistry;
|
|
4750
|
+
if (registry == null) {
|
|
4751
|
+
throw new CofheError({
|
|
4752
|
+
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
4753
|
+
message: `No ACP share registry available for chainId <${chainId}>`,
|
|
4754
|
+
hint: "The ACL on this chain does not serve a share registry address. Set `acp.sharingRegistry` in the cofhe config to use on-chain sharing.",
|
|
4755
|
+
context: { chainId }
|
|
4756
|
+
});
|
|
4757
|
+
}
|
|
4758
|
+
return registry;
|
|
4759
|
+
};
|
|
4431
4760
|
const _requireConnected = () => {
|
|
4432
4761
|
const state = connectStore.getState();
|
|
4433
4762
|
const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
|
|
@@ -4550,74 +4879,147 @@ function createCofheClientBase(opts) {
|
|
|
4550
4879
|
}
|
|
4551
4880
|
return { chainId: _chainId, account: _account };
|
|
4552
4881
|
};
|
|
4553
|
-
const
|
|
4882
|
+
const clientACPs = {
|
|
4554
4883
|
// Pass through store access
|
|
4555
|
-
getSnapshot:
|
|
4556
|
-
subscribe:
|
|
4884
|
+
getSnapshot: acps.getSnapshot,
|
|
4885
|
+
subscribe: acps.subscribe,
|
|
4557
4886
|
// Creation methods (require connection)
|
|
4558
4887
|
createSelf: async (options, clients) => {
|
|
4559
4888
|
_requireConnected();
|
|
4560
4889
|
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
4561
|
-
|
|
4890
|
+
const chainId = await publicClient.getChainId();
|
|
4891
|
+
return acps.createSelf(
|
|
4892
|
+
await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, chainId),
|
|
4893
|
+
publicClient,
|
|
4894
|
+
walletClient
|
|
4895
|
+
);
|
|
4562
4896
|
},
|
|
4563
4897
|
createSharing: async (options, clients) => {
|
|
4564
4898
|
_requireConnected();
|
|
4565
4899
|
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
4566
|
-
|
|
4900
|
+
const chainId = await publicClient.getChainId();
|
|
4901
|
+
return acps.createSharing(
|
|
4902
|
+
await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, chainId),
|
|
4903
|
+
publicClient,
|
|
4904
|
+
walletClient
|
|
4905
|
+
);
|
|
4567
4906
|
},
|
|
4568
4907
|
importShared: async (options, clients) => {
|
|
4569
4908
|
_requireConnected();
|
|
4570
4909
|
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
4571
|
-
return
|
|
4910
|
+
return acps.importShared(options, publicClient, walletClient);
|
|
4572
4911
|
},
|
|
4573
4912
|
// Get or create methods (require connection)
|
|
4574
|
-
|
|
4913
|
+
getOrCreateSelfACP: async (chainId, account, options) => {
|
|
4575
4914
|
_requireConnected();
|
|
4576
4915
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4577
4916
|
const { publicClient, walletClient } = connectStore.getState();
|
|
4578
|
-
|
|
4917
|
+
const optionsWithDefaults = await acps.applyACPDefaultsFromChain(
|
|
4918
|
+
options ?? { issuer: _account, name: "Autogenerated Self ACP" },
|
|
4919
|
+
opts.config.acp,
|
|
4920
|
+
publicClient,
|
|
4921
|
+
_chainId
|
|
4922
|
+
);
|
|
4923
|
+
return acps.getOrCreateSelfACP(publicClient, walletClient, _chainId, _account, optionsWithDefaults);
|
|
4579
4924
|
},
|
|
4580
|
-
|
|
4925
|
+
getOrCreateSharingACP: async (options, chainId, account) => {
|
|
4581
4926
|
_requireConnected();
|
|
4582
4927
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4583
4928
|
const { publicClient, walletClient } = connectStore.getState();
|
|
4584
|
-
return
|
|
4929
|
+
return acps.getOrCreateSharingACP(
|
|
4930
|
+
publicClient,
|
|
4931
|
+
walletClient,
|
|
4932
|
+
await acps.applyACPDefaultsFromChain(options, opts.config.acp, publicClient, _chainId),
|
|
4933
|
+
_chainId,
|
|
4934
|
+
_account
|
|
4935
|
+
);
|
|
4936
|
+
},
|
|
4937
|
+
// Revocation (require connection)
|
|
4938
|
+
revokeACP: async (acp) => {
|
|
4939
|
+
_requireConnected();
|
|
4940
|
+
const { walletClient } = connectStore.getState();
|
|
4941
|
+
return acps.revokeACP(acp, walletClient);
|
|
4942
|
+
},
|
|
4943
|
+
revokeAllACPs: async (revokerContract) => {
|
|
4944
|
+
_requireConnected();
|
|
4945
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
4946
|
+
return acps.revokeAllACPs(walletClient, publicClient, revokerContract);
|
|
4947
|
+
},
|
|
4948
|
+
isACPRevoked: async (acp) => {
|
|
4949
|
+
_requireConnected();
|
|
4950
|
+
const { publicClient } = connectStore.getState();
|
|
4951
|
+
return acps.isACPRevoked(acp, publicClient);
|
|
4952
|
+
},
|
|
4953
|
+
// On-chain sharing (require connection + config.acp.sharingRegistry)
|
|
4954
|
+
shareOnChain: async (acp) => {
|
|
4955
|
+
_requireConnected();
|
|
4956
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
4957
|
+
const chainId = await publicClient.getChainId();
|
|
4958
|
+
const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
|
|
4959
|
+
return acps.shareOnChain(acp, walletClient, sharingRegistry);
|
|
4960
|
+
},
|
|
4961
|
+
getIncomingShares: async () => {
|
|
4962
|
+
_requireConnected();
|
|
4963
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
4964
|
+
const chainId = await publicClient.getChainId();
|
|
4965
|
+
const account = walletClient.account.address;
|
|
4966
|
+
const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
|
|
4967
|
+
return acps.getIncomingShares(publicClient, sharingRegistry, account);
|
|
4968
|
+
},
|
|
4969
|
+
importFromChain: async (share) => {
|
|
4970
|
+
_requireConnected();
|
|
4971
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
4972
|
+
return acps.importFromChain(share, publicClient, walletClient);
|
|
4973
|
+
},
|
|
4974
|
+
dismissShare: async (shareId) => {
|
|
4975
|
+
_requireConnected();
|
|
4976
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
4977
|
+
const chainId = await publicClient.getChainId();
|
|
4978
|
+
const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
|
|
4979
|
+
return acps.removeShareOnChain(shareId, walletClient, sharingRegistry);
|
|
4980
|
+
},
|
|
4981
|
+
cancelShare: async (shareId) => {
|
|
4982
|
+
_requireConnected();
|
|
4983
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
4984
|
+
const chainId = await publicClient.getChainId();
|
|
4985
|
+
const sharingRegistry = await _resolveSharingRegistry(publicClient, chainId);
|
|
4986
|
+
return acps.removeShareOnChain(shareId, walletClient, sharingRegistry);
|
|
4585
4987
|
},
|
|
4586
4988
|
// Retrieval methods (auto-fill chainId/account)
|
|
4587
|
-
|
|
4989
|
+
getACP: (hash, chainId, account) => {
|
|
4588
4990
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4589
|
-
return
|
|
4991
|
+
return acps.getACP(_chainId, _account, hash);
|
|
4590
4992
|
},
|
|
4591
|
-
|
|
4993
|
+
getACPs: (chainId, account) => {
|
|
4592
4994
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4593
|
-
return
|
|
4995
|
+
return acps.getACPs(_chainId, _account);
|
|
4594
4996
|
},
|
|
4595
|
-
|
|
4997
|
+
getActiveACP: (chainId, account) => {
|
|
4596
4998
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4597
|
-
return
|
|
4999
|
+
return acps.getActiveACP(_chainId, _account);
|
|
4598
5000
|
},
|
|
4599
|
-
|
|
5001
|
+
getActiveACPHash: (chainId, account) => {
|
|
4600
5002
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4601
|
-
return
|
|
5003
|
+
return acps.getActiveACPHash(_chainId, _account);
|
|
4602
5004
|
},
|
|
4603
5005
|
// Mutation methods (auto-fill chainId/account)
|
|
4604
|
-
|
|
5006
|
+
selectActiveACP: (hash, chainId, account) => {
|
|
4605
5007
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4606
|
-
return
|
|
5008
|
+
return acps.selectActiveACP(_chainId, _account, hash);
|
|
4607
5009
|
},
|
|
4608
|
-
|
|
5010
|
+
removeACP: async (hash, chainId, account) => {
|
|
4609
5011
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4610
|
-
return
|
|
5012
|
+
return acps.removeACP(_chainId, _account, hash);
|
|
4611
5013
|
},
|
|
4612
|
-
|
|
5014
|
+
removeActiveACP: async (chainId, account) => {
|
|
4613
5015
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
4614
|
-
return
|
|
5016
|
+
return acps.removeActiveACP(_chainId, _account);
|
|
4615
5017
|
},
|
|
4616
5018
|
// Utils (no context needed)
|
|
4617
|
-
getHash:
|
|
4618
|
-
export:
|
|
4619
|
-
serialize:
|
|
4620
|
-
deserialize:
|
|
5019
|
+
getHash: acps.getHash,
|
|
5020
|
+
export: acps.export,
|
|
5021
|
+
serialize: acps.serialize,
|
|
5022
|
+
deserialize: acps.deserialize
|
|
4621
5023
|
};
|
|
4622
5024
|
return {
|
|
4623
5025
|
// Zustand reactive accessors (don't export store directly to prevent mutation)
|
|
@@ -4645,7 +5047,7 @@ function createCofheClientBase(opts) {
|
|
|
4645
5047
|
decryptHandle: decryptForView,
|
|
4646
5048
|
decryptForTx,
|
|
4647
5049
|
verifyDecryptResult: verifyDecryptResult2,
|
|
4648
|
-
|
|
5050
|
+
acp: clientACPs
|
|
4649
5051
|
// Add SDK-specific methods below that require connection
|
|
4650
5052
|
// Example:
|
|
4651
5053
|
// async encryptData(data: unknown) {
|
|
@@ -4674,15 +5076,18 @@ exports.MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_
|
|
|
4674
5076
|
exports.TASK_MANAGER_ADDRESS = TASK_MANAGER_ADDRESS;
|
|
4675
5077
|
exports.TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT = TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT;
|
|
4676
5078
|
exports.TFHE_RS_ZK_MAX_BITS = TFHE_RS_ZK_MAX_BITS;
|
|
4677
|
-
exports.
|
|
5079
|
+
exports.assertNoRenamedConfigKeys = assertNoRenamedConfigKeys;
|
|
5080
|
+
exports.cofheFetch = cofheFetch;
|
|
4678
5081
|
exports.createCofheClientBase = createCofheClientBase;
|
|
4679
5082
|
exports.createCofheConfigBase = createCofheConfigBase;
|
|
4680
5083
|
exports.createKeysStore = createKeysStore;
|
|
4681
5084
|
exports.fetchKeys = fetchKeys;
|
|
4682
5085
|
exports.fheTypeToString = fheTypeToString;
|
|
4683
5086
|
exports.getCofheConfigItem = getCofheConfigItem;
|
|
5087
|
+
exports.getCofheDebugInterceptors = getCofheDebugInterceptors;
|
|
4684
5088
|
exports.isCofheError = isCofheError;
|
|
4685
5089
|
exports.isEncryptableItem = isEncryptableItem;
|
|
4686
5090
|
exports.isLastEncryptionStep = isLastEncryptionStep;
|
|
5091
|
+
exports.setCofheDebugInterceptors = setCofheDebugInterceptors;
|
|
4687
5092
|
exports.verifyDecryptResult = verifyDecryptResult;
|
|
4688
5093
|
exports.zkProveWithWorker = zkProveWithWorker;
|