@cofhe/sdk 0.2.0 → 0.3.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 +36 -0
- package/chains/defineChain.ts +2 -2
- package/chains/types.ts +3 -3
- package/core/baseBuilder.ts +18 -18
- package/core/client.test.ts +155 -41
- package/core/client.ts +72 -32
- package/core/clientTypes.ts +28 -18
- package/core/config.test.ts +40 -33
- package/core/config.ts +56 -51
- package/core/consts.ts +22 -0
- package/core/decrypt/{MockQueryDecrypterAbi.ts → MockThresholdNetworkAbi.ts} +71 -21
- package/core/decrypt/cofheMocksDecryptForTx.ts +142 -0
- package/core/decrypt/{cofheMocksSealOutput.ts → cofheMocksDecryptForView.ts} +12 -14
- package/core/decrypt/decryptForTxBuilder.ts +340 -0
- package/core/decrypt/{decryptHandleBuilder.ts → decryptForViewBuilder.ts} +75 -42
- package/core/decrypt/tnDecrypt.ts +232 -0
- package/core/decrypt/tnSealOutputV1.ts +5 -5
- package/core/decrypt/tnSealOutputV2.ts +27 -27
- package/core/encrypt/cofheMocksZkVerifySign.ts +19 -26
- package/core/encrypt/encryptInputsBuilder.test.ts +57 -61
- package/core/encrypt/encryptInputsBuilder.ts +65 -42
- package/core/encrypt/zkPackProveVerify.ts +11 -11
- package/core/error.ts +18 -18
- package/core/fetchKeys.test.ts +3 -3
- package/core/fetchKeys.ts +3 -3
- package/core/index.ts +22 -11
- package/core/permits.test.ts +5 -6
- package/core/permits.ts +5 -4
- package/core/utils.ts +10 -10
- package/dist/chains.cjs +4 -7
- package/dist/chains.d.cts +12 -12
- package/dist/chains.d.ts +12 -12
- package/dist/chains.js +1 -1
- package/dist/{chunk-WGCRJCBR.js → chunk-2TPSCOW3.js} +820 -224
- package/dist/{chunk-UGBVZNRT.js → chunk-NWDKXBIP.js} +309 -189
- package/dist/{chunk-WEAZ25JO.js → chunk-TBLR7NNE.js} +4 -7
- package/dist/{clientTypes-5_1nwtUe.d.cts → clientTypes-6aTZPQ_4.d.ts} +233 -173
- package/dist/{clientTypes-Es7fyi65.d.ts → clientTypes-Bhq7pCSA.d.cts} +233 -173
- package/dist/core.cjs +1138 -418
- package/dist/core.d.cts +37 -24
- package/dist/core.d.ts +37 -24
- package/dist/core.js +3 -3
- package/dist/node.cjs +1082 -370
- package/dist/node.d.cts +12 -12
- package/dist/node.d.ts +12 -12
- package/dist/node.js +8 -8
- package/dist/{permit-fUSe6KKq.d.cts → permit-MZ502UBl.d.cts} +30 -33
- package/dist/{permit-fUSe6KKq.d.ts → permit-MZ502UBl.d.ts} +30 -33
- package/dist/permits.cjs +305 -187
- package/dist/permits.d.cts +111 -812
- package/dist/permits.d.ts +111 -812
- package/dist/permits.js +1 -1
- package/dist/types-YiAC4gig.d.cts +33 -0
- package/dist/types-YiAC4gig.d.ts +33 -0
- package/dist/web.cjs +1085 -373
- package/dist/web.d.cts +13 -13
- package/dist/web.d.ts +13 -13
- package/dist/web.js +10 -10
- package/node/client.test.ts +34 -34
- package/node/config.test.ts +11 -11
- package/node/encryptInputs.test.ts +29 -29
- package/node/index.ts +15 -15
- package/package.json +3 -3
- package/permits/localstorage.test.ts +9 -13
- package/permits/onchain-utils.ts +221 -0
- package/permits/permit.test.ts +51 -5
- package/permits/permit.ts +28 -74
- package/permits/store.test.ts +10 -50
- package/permits/store.ts +4 -14
- package/permits/test-utils.ts +10 -2
- package/permits/types.ts +22 -9
- package/permits/utils.ts +0 -4
- package/permits/validation.test.ts +29 -32
- package/permits/validation.ts +112 -194
- package/web/client.web.test.ts +34 -34
- package/web/config.web.test.ts +11 -11
- package/web/encryptInputs.web.test.ts +29 -29
- package/web/index.ts +19 -19
- package/web/worker.builder.web.test.ts +28 -28
- package/web/worker.config.web.test.ts +47 -47
- package/web/worker.output.web.test.ts +10 -10
- package/dist/types-KImPrEIe.d.cts +0 -48
- package/dist/types-KImPrEIe.d.ts +0 -48
package/dist/node.cjs
CHANGED
|
@@ -35,7 +35,7 @@ var nacl__namespace = /*#__PURE__*/_interopNamespace(nacl);
|
|
|
35
35
|
// core/client.ts
|
|
36
36
|
|
|
37
37
|
// core/error.ts
|
|
38
|
-
var
|
|
38
|
+
var CofheError = class _CofheError extends Error {
|
|
39
39
|
code;
|
|
40
40
|
cause;
|
|
41
41
|
hint;
|
|
@@ -43,25 +43,25 @@ var CofhesdkError = class _CofhesdkError extends Error {
|
|
|
43
43
|
constructor({ code, message, cause, hint, context }) {
|
|
44
44
|
const fullMessage = cause ? `${message} | Caused by: ${cause.message}` : message;
|
|
45
45
|
super(fullMessage);
|
|
46
|
-
this.name = "
|
|
46
|
+
this.name = "CofheError";
|
|
47
47
|
this.code = code;
|
|
48
48
|
this.cause = cause;
|
|
49
49
|
this.hint = hint;
|
|
50
50
|
this.context = context;
|
|
51
51
|
if (Error.captureStackTrace) {
|
|
52
|
-
Error.captureStackTrace(this,
|
|
52
|
+
Error.captureStackTrace(this, _CofheError);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* Creates a
|
|
57
|
-
* If the error is a
|
|
58
|
-
* If a wrapperError is provided, it is used to create the new
|
|
56
|
+
* Creates a CofheError from an unknown error
|
|
57
|
+
* If the error is a CofheError, it is returned unchanged, else a new CofheError is created
|
|
58
|
+
* If a wrapperError is provided, it is used to create the new CofheError, else a default is used
|
|
59
59
|
*/
|
|
60
60
|
static fromError(error, wrapperError) {
|
|
61
|
-
if (
|
|
61
|
+
if (isCofheError(error))
|
|
62
62
|
return error;
|
|
63
63
|
const cause = error instanceof Error ? error : new Error(`${error}`);
|
|
64
|
-
return new
|
|
64
|
+
return new _CofheError({
|
|
65
65
|
code: wrapperError?.code ?? "INTERNAL_ERROR" /* InternalError */,
|
|
66
66
|
message: wrapperError?.message ?? "An internal error occurred",
|
|
67
67
|
hint: wrapperError?.hint,
|
|
@@ -121,7 +121,7 @@ var bigintSafeJsonStringify = (value) => {
|
|
|
121
121
|
return value2;
|
|
122
122
|
});
|
|
123
123
|
};
|
|
124
|
-
var
|
|
124
|
+
var isCofheError = (error) => error instanceof CofheError;
|
|
125
125
|
|
|
126
126
|
// core/types.ts
|
|
127
127
|
var FheUintUTypes = [
|
|
@@ -165,14 +165,14 @@ async function getPublicClientChainID(publicClient) {
|
|
|
165
165
|
try {
|
|
166
166
|
chainId = publicClient.chain?.id ?? await publicClient.getChainId();
|
|
167
167
|
} catch (e) {
|
|
168
|
-
throw new
|
|
168
|
+
throw new CofheError({
|
|
169
169
|
code: "PUBLIC_WALLET_GET_CHAIN_ID_FAILED" /* PublicWalletGetChainIdFailed */,
|
|
170
170
|
message: "getting chain ID from public client failed",
|
|
171
171
|
cause: e instanceof Error ? e : void 0
|
|
172
172
|
});
|
|
173
173
|
}
|
|
174
174
|
if (chainId === null) {
|
|
175
|
-
throw new
|
|
175
|
+
throw new CofheError({
|
|
176
176
|
code: "PUBLIC_WALLET_GET_CHAIN_ID_FAILED" /* PublicWalletGetChainIdFailed */,
|
|
177
177
|
message: "chain ID from public client is null"
|
|
178
178
|
});
|
|
@@ -187,14 +187,14 @@ async function getWalletClientAccount(walletClient) {
|
|
|
187
187
|
address = (await walletClient.getAddresses())?.[0];
|
|
188
188
|
}
|
|
189
189
|
} catch (e) {
|
|
190
|
-
throw new
|
|
190
|
+
throw new CofheError({
|
|
191
191
|
code: "PUBLIC_WALLET_GET_ADDRESSES_FAILED" /* PublicWalletGetAddressesFailed */,
|
|
192
192
|
message: "getting address from wallet client failed",
|
|
193
193
|
cause: e instanceof Error ? e : void 0
|
|
194
194
|
});
|
|
195
195
|
}
|
|
196
196
|
if (!address) {
|
|
197
|
-
throw new
|
|
197
|
+
throw new CofheError({
|
|
198
198
|
code: "PUBLIC_WALLET_GET_ADDRESSES_FAILED" /* PublicWalletGetAddressesFailed */,
|
|
199
199
|
message: "address from wallet client is null"
|
|
200
200
|
});
|
|
@@ -262,7 +262,7 @@ var zkPack = (items, builder) => {
|
|
|
262
262
|
break;
|
|
263
263
|
}
|
|
264
264
|
default: {
|
|
265
|
-
throw new
|
|
265
|
+
throw new CofheError({
|
|
266
266
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
267
267
|
message: `Invalid utype: ${item.utype}`,
|
|
268
268
|
hint: `Ensure that the utype is valid, using the Encryptable type, for example: Encryptable.uint128(100n)`,
|
|
@@ -274,7 +274,7 @@ var zkPack = (items, builder) => {
|
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
if (totalBits > MAX_ENCRYPTABLE_BITS) {
|
|
277
|
-
throw new
|
|
277
|
+
throw new CofheError({
|
|
278
278
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
279
279
|
message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
|
|
280
280
|
hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
|
|
@@ -338,14 +338,14 @@ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chain
|
|
|
338
338
|
});
|
|
339
339
|
if (!response.ok) {
|
|
340
340
|
const errorBody = await response.text();
|
|
341
|
-
throw new
|
|
341
|
+
throw new CofheError({
|
|
342
342
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
343
343
|
message: `HTTP error! ZK proof verification failed - ${errorBody}`
|
|
344
344
|
});
|
|
345
345
|
}
|
|
346
346
|
const json = await response.json();
|
|
347
347
|
if (json.status !== "success") {
|
|
348
|
-
throw new
|
|
348
|
+
throw new CofheError({
|
|
349
349
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
350
350
|
message: `ZK proof verification response malformed - ${json.error}`
|
|
351
351
|
});
|
|
@@ -357,7 +357,7 @@ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chain
|
|
|
357
357
|
};
|
|
358
358
|
});
|
|
359
359
|
} catch (e) {
|
|
360
|
-
throw new
|
|
360
|
+
throw new CofheError({
|
|
361
361
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
362
362
|
message: `ZK proof verification failed`,
|
|
363
363
|
cause: e instanceof Error ? e : void 0
|
|
@@ -475,8 +475,15 @@ var MockZkVerifierAbi = [
|
|
|
475
475
|
},
|
|
476
476
|
{ type: "error", name: "InvalidInputs", inputs: [] }
|
|
477
477
|
];
|
|
478
|
-
|
|
478
|
+
|
|
479
|
+
// core/consts.ts
|
|
480
|
+
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
481
|
+
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
482
|
+
var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
479
483
|
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
484
|
+
var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
|
|
485
|
+
|
|
486
|
+
// core/encrypt/cofheMocksZkVerifySign.ts
|
|
480
487
|
function createMockZkVerifierSigner() {
|
|
481
488
|
return viem.createWalletClient({
|
|
482
489
|
chain: chains.hardhat,
|
|
@@ -519,7 +526,7 @@ async function cofheMocksCheckEncryptableBits(items) {
|
|
|
519
526
|
}
|
|
520
527
|
}
|
|
521
528
|
if (totalBits > MAX_ENCRYPTABLE_BITS) {
|
|
522
|
-
throw new
|
|
529
|
+
throw new CofheError({
|
|
523
530
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
524
531
|
message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
|
|
525
532
|
hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
|
|
@@ -542,18 +549,18 @@ async function calcCtHashes(items, account, securityZone, publicClient) {
|
|
|
542
549
|
let ctHashes;
|
|
543
550
|
try {
|
|
544
551
|
ctHashes = await publicClient.readContract({
|
|
545
|
-
address:
|
|
552
|
+
address: MOCKS_ZK_VERIFIER_ADDRESS,
|
|
546
553
|
abi: MockZkVerifierAbi,
|
|
547
554
|
functionName: "zkVerifyCalcCtHashesPacked",
|
|
548
555
|
args: calcCtHashesArgs
|
|
549
556
|
});
|
|
550
557
|
} catch (err) {
|
|
551
|
-
throw new
|
|
558
|
+
throw new CofheError({
|
|
552
559
|
code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
|
|
553
560
|
message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
|
|
554
561
|
cause: err instanceof Error ? err : void 0,
|
|
555
562
|
context: {
|
|
556
|
-
address:
|
|
563
|
+
address: MOCKS_ZK_VERIFIER_ADDRESS,
|
|
557
564
|
items,
|
|
558
565
|
account,
|
|
559
566
|
securityZone,
|
|
@@ -563,7 +570,7 @@ async function calcCtHashes(items, account, securityZone, publicClient) {
|
|
|
563
570
|
});
|
|
564
571
|
}
|
|
565
572
|
if (ctHashes.length !== items.length) {
|
|
566
|
-
throw new
|
|
573
|
+
throw new CofheError({
|
|
567
574
|
code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
|
|
568
575
|
message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
|
|
569
576
|
context: {
|
|
@@ -586,7 +593,7 @@ async function insertCtHashes(items, walletClient) {
|
|
|
586
593
|
try {
|
|
587
594
|
const account = walletClient.account;
|
|
588
595
|
await walletClient.writeContract({
|
|
589
|
-
address:
|
|
596
|
+
address: MOCKS_ZK_VERIFIER_ADDRESS,
|
|
590
597
|
abi: MockZkVerifierAbi,
|
|
591
598
|
functionName: "insertPackedCtHashes",
|
|
592
599
|
args: insertPackedCtHashesArgs,
|
|
@@ -594,7 +601,7 @@ async function insertCtHashes(items, walletClient) {
|
|
|
594
601
|
account
|
|
595
602
|
});
|
|
596
603
|
} catch (err) {
|
|
597
|
-
throw new
|
|
604
|
+
throw new CofheError({
|
|
598
605
|
code: "ZK_MOCKS_INSERT_CT_HASHES_FAILED" /* ZkMocksInsertCtHashesFailed */,
|
|
599
606
|
message: `mockZkVerifySign insertPackedCtHashes failed while calling insertPackedCtHashes`,
|
|
600
607
|
cause: err instanceof Error ? err : void 0,
|
|
@@ -612,7 +619,7 @@ async function createProofSignatures(items, securityZone) {
|
|
|
612
619
|
try {
|
|
613
620
|
encInputSignerClient = createMockZkVerifierSigner();
|
|
614
621
|
} catch (err) {
|
|
615
|
-
throw new
|
|
622
|
+
throw new CofheError({
|
|
616
623
|
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
617
624
|
message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
|
|
618
625
|
cause: err instanceof Error ? err : void 0,
|
|
@@ -633,7 +640,7 @@ async function createProofSignatures(items, securityZone) {
|
|
|
633
640
|
signatures.push(signature);
|
|
634
641
|
}
|
|
635
642
|
} catch (err) {
|
|
636
|
-
throw new
|
|
643
|
+
throw new CofheError({
|
|
637
644
|
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
638
645
|
message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
|
|
639
646
|
cause: err instanceof Error ? err : void 0,
|
|
@@ -644,7 +651,7 @@ async function createProofSignatures(items, securityZone) {
|
|
|
644
651
|
});
|
|
645
652
|
}
|
|
646
653
|
if (signatures.length !== items.length) {
|
|
647
|
-
throw new
|
|
654
|
+
throw new CofheError({
|
|
648
655
|
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
649
656
|
message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
|
|
650
657
|
context: {
|
|
@@ -674,21 +681,18 @@ var CofheChainSchema = zod.z.object({
|
|
|
674
681
|
/** Network identifier */
|
|
675
682
|
network: zod.z.string().min(1),
|
|
676
683
|
/** coFhe service URL */
|
|
677
|
-
coFheUrl: zod.z.
|
|
684
|
+
coFheUrl: zod.z.url(),
|
|
678
685
|
/** Verifier service URL */
|
|
679
|
-
verifierUrl: zod.z.
|
|
686
|
+
verifierUrl: zod.z.url(),
|
|
680
687
|
/** Threshold network service URL */
|
|
681
|
-
thresholdNetworkUrl: zod.z.
|
|
688
|
+
thresholdNetworkUrl: zod.z.url(),
|
|
682
689
|
/** Environment type */
|
|
683
690
|
environment: EnvironmentSchema
|
|
684
691
|
});
|
|
685
|
-
|
|
686
|
-
// chains/defineChain.ts
|
|
687
692
|
function defineChain(chainConfig) {
|
|
688
693
|
const result = CofheChainSchema.safeParse(chainConfig);
|
|
689
694
|
if (!result.success) {
|
|
690
|
-
|
|
691
|
-
throw new Error(`Invalid chain configuration: ${errorMessages.join(", ")}`);
|
|
695
|
+
throw new Error(`Invalid chain configuration: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
|
|
692
696
|
}
|
|
693
697
|
return result.data;
|
|
694
698
|
}
|
|
@@ -704,43 +708,48 @@ var hardhat2 = defineChain({
|
|
|
704
708
|
thresholdNetworkUrl: "http://127.0.0.1:3000",
|
|
705
709
|
environment: "MOCK"
|
|
706
710
|
});
|
|
707
|
-
var
|
|
711
|
+
var CofheConfigSchema = zod.z.object({
|
|
708
712
|
/** Environment that the SDK is running in */
|
|
709
713
|
environment: zod.z.enum(["node", "hardhat", "web", "react"]).optional().default("node"),
|
|
710
714
|
/** List of supported chain configurations */
|
|
711
715
|
supportedChains: zod.z.array(zod.z.custom()),
|
|
712
|
-
/** How permits are generated */
|
|
713
|
-
permitGeneration: zod.z.enum(["ON_CONNECT", "ON_DECRYPT_HANDLES", "MANUAL"]).optional().default("ON_CONNECT"),
|
|
714
716
|
/** Default permit expiration in seconds, default is 30 days */
|
|
715
717
|
defaultPermitExpiration: zod.z.number().optional().default(60 * 60 * 24 * 30),
|
|
716
718
|
/** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
|
|
717
719
|
fheKeyStorage: zod.z.object({
|
|
718
|
-
getItem: zod.z.
|
|
719
|
-
|
|
720
|
-
|
|
720
|
+
getItem: zod.z.custom((val) => typeof val === "function", {
|
|
721
|
+
message: "getItem must be a function"
|
|
722
|
+
}),
|
|
723
|
+
setItem: zod.z.custom((val) => typeof val === "function", {
|
|
724
|
+
message: "setItem must be a function"
|
|
725
|
+
}),
|
|
726
|
+
removeItem: zod.z.custom((val) => typeof val === "function", {
|
|
727
|
+
message: "removeItem must be a function"
|
|
728
|
+
})
|
|
721
729
|
}).or(zod.z.null()).default(null),
|
|
722
730
|
/** Whether to use Web Workers for ZK proof generation (web platform only) */
|
|
723
731
|
useWorkers: zod.z.boolean().optional().default(true),
|
|
724
732
|
/** Mocks configs */
|
|
725
733
|
mocks: zod.z.object({
|
|
726
|
-
|
|
727
|
-
|
|
734
|
+
decryptDelay: zod.z.number().optional().default(0),
|
|
735
|
+
encryptDelay: zod.z.union([zod.z.number(), zod.z.tuple([zod.z.number(), zod.z.number(), zod.z.number(), zod.z.number(), zod.z.number()])]).optional().default([100, 100, 100, 500, 500])
|
|
736
|
+
}).optional().default({ decryptDelay: 0, encryptDelay: [100, 100, 100, 500, 500] }),
|
|
728
737
|
/** Internal configuration */
|
|
729
738
|
_internal: zod.z.object({
|
|
730
739
|
zkvWalletClient: zod.z.any().optional()
|
|
731
740
|
}).optional()
|
|
732
741
|
});
|
|
733
|
-
function
|
|
734
|
-
const result =
|
|
742
|
+
function createCofheConfigBase(config) {
|
|
743
|
+
const result = CofheConfigSchema.safeParse(config);
|
|
735
744
|
if (!result.success) {
|
|
736
|
-
throw new Error(`Invalid
|
|
745
|
+
throw new Error(`Invalid cofhe configuration: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
|
|
737
746
|
}
|
|
738
747
|
return result.data;
|
|
739
748
|
}
|
|
740
749
|
function getSupportedChainOrThrow(config, chainId) {
|
|
741
750
|
const supportedChain = config.supportedChains.find((chain) => chain.id === chainId);
|
|
742
751
|
if (!supportedChain) {
|
|
743
|
-
throw new
|
|
752
|
+
throw new CofheError({
|
|
744
753
|
code: "UNSUPPORTED_CHAIN" /* UnsupportedChain */,
|
|
745
754
|
message: `Config does not support chain <${chainId}>`,
|
|
746
755
|
hint: "Ensure config passed to client has been created with this chain in the config.supportedChains array.",
|
|
@@ -756,7 +765,7 @@ function getCoFheUrlOrThrow(config, chainId) {
|
|
|
756
765
|
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
757
766
|
const url = supportedChain.coFheUrl;
|
|
758
767
|
if (!url) {
|
|
759
|
-
throw new
|
|
768
|
+
throw new CofheError({
|
|
760
769
|
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
761
770
|
message: `CoFHE URL is not configured for chain <${chainId}>`,
|
|
762
771
|
hint: "Ensure this chain config includes a coFheUrl property.",
|
|
@@ -769,7 +778,7 @@ function getZkVerifierUrlOrThrow(config, chainId) {
|
|
|
769
778
|
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
770
779
|
const url = supportedChain.verifierUrl;
|
|
771
780
|
if (!url) {
|
|
772
|
-
throw new
|
|
781
|
+
throw new CofheError({
|
|
773
782
|
code: "ZK_VERIFIER_URL_UNINITIALIZED" /* ZkVerifierUrlUninitialized */,
|
|
774
783
|
message: `ZK verifier URL is not configured for chain <${chainId}>`,
|
|
775
784
|
hint: "Ensure this chain config includes a verifierUrl property.",
|
|
@@ -782,7 +791,7 @@ function getThresholdNetworkUrlOrThrow(config, chainId) {
|
|
|
782
791
|
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
783
792
|
const url = supportedChain.thresholdNetworkUrl;
|
|
784
793
|
if (!url) {
|
|
785
|
-
throw new
|
|
794
|
+
throw new CofheError({
|
|
786
795
|
code: "THRESHOLD_NETWORK_URL_UNINITIALIZED" /* ThresholdNetworkUrlUninitialized */,
|
|
787
796
|
message: `Threshold network URL is not configured for chain <${chainId}>`,
|
|
788
797
|
hint: "Ensure this chain config includes a thresholdNetworkUrl property.",
|
|
@@ -994,7 +1003,7 @@ var BaseBuilder = class {
|
|
|
994
1003
|
account;
|
|
995
1004
|
constructor(params) {
|
|
996
1005
|
if (!params.config) {
|
|
997
|
-
throw new
|
|
1006
|
+
throw new CofheError({
|
|
998
1007
|
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
999
1008
|
message: "Builder config is undefined",
|
|
1000
1009
|
hint: "Ensure client has been created with a config.",
|
|
@@ -1012,12 +1021,12 @@ var BaseBuilder = class {
|
|
|
1012
1021
|
}
|
|
1013
1022
|
/**
|
|
1014
1023
|
* Asserts that this.chainId is populated
|
|
1015
|
-
* @throws {
|
|
1024
|
+
* @throws {CofheError} If chainId is not set
|
|
1016
1025
|
*/
|
|
1017
1026
|
assertChainId() {
|
|
1018
1027
|
if (this.chainId)
|
|
1019
1028
|
return;
|
|
1020
|
-
throw new
|
|
1029
|
+
throw new CofheError({
|
|
1021
1030
|
code: "CHAIN_ID_UNINITIALIZED" /* ChainIdUninitialized */,
|
|
1022
1031
|
message: "Chain ID is not set",
|
|
1023
1032
|
hint: "Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.",
|
|
@@ -1028,12 +1037,12 @@ var BaseBuilder = class {
|
|
|
1028
1037
|
}
|
|
1029
1038
|
/**
|
|
1030
1039
|
* Asserts that this.account is populated
|
|
1031
|
-
* @throws {
|
|
1040
|
+
* @throws {CofheError} If account is not set
|
|
1032
1041
|
*/
|
|
1033
1042
|
assertAccount() {
|
|
1034
1043
|
if (this.account)
|
|
1035
1044
|
return;
|
|
1036
|
-
throw new
|
|
1045
|
+
throw new CofheError({
|
|
1037
1046
|
code: "ACCOUNT_UNINITIALIZED" /* AccountUninitialized */,
|
|
1038
1047
|
message: "Account is not set",
|
|
1039
1048
|
hint: "Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.",
|
|
@@ -1044,12 +1053,12 @@ var BaseBuilder = class {
|
|
|
1044
1053
|
}
|
|
1045
1054
|
/**
|
|
1046
1055
|
* Asserts that this.publicClient is populated
|
|
1047
|
-
* @throws {
|
|
1056
|
+
* @throws {CofheError} If publicClient is not set
|
|
1048
1057
|
*/
|
|
1049
1058
|
assertPublicClient() {
|
|
1050
1059
|
if (this.publicClient)
|
|
1051
1060
|
return;
|
|
1052
|
-
throw new
|
|
1061
|
+
throw new CofheError({
|
|
1053
1062
|
code: "MISSING_PUBLIC_CLIENT" /* MissingPublicClient */,
|
|
1054
1063
|
message: "Public client not found",
|
|
1055
1064
|
hint: "Ensure client.connect() has been called with a publicClient.",
|
|
@@ -1060,12 +1069,12 @@ var BaseBuilder = class {
|
|
|
1060
1069
|
}
|
|
1061
1070
|
/**
|
|
1062
1071
|
* Asserts that this.walletClient is populated
|
|
1063
|
-
* @throws {
|
|
1072
|
+
* @throws {CofheError} If walletClient is not set
|
|
1064
1073
|
*/
|
|
1065
1074
|
assertWalletClient() {
|
|
1066
1075
|
if (this.walletClient)
|
|
1067
1076
|
return;
|
|
1068
|
-
throw new
|
|
1077
|
+
throw new CofheError({
|
|
1069
1078
|
code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
|
|
1070
1079
|
message: "Wallet client not found",
|
|
1071
1080
|
hint: "Ensure client.connect() has been called with a walletClient.",
|
|
@@ -1110,7 +1119,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1110
1119
|
this.securityZone = params.securityZone ?? 0;
|
|
1111
1120
|
this.zkvWalletClient = params.zkvWalletClient;
|
|
1112
1121
|
if (!params.tfhePublicKeyDeserializer) {
|
|
1113
|
-
throw new
|
|
1122
|
+
throw new CofheError({
|
|
1114
1123
|
code: "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER" /* MissingTfhePublicKeyDeserializer */,
|
|
1115
1124
|
message: "EncryptInputsBuilder tfhePublicKeyDeserializer is undefined",
|
|
1116
1125
|
hint: "Ensure client has been created with a tfhePublicKeyDeserializer.",
|
|
@@ -1121,7 +1130,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1121
1130
|
}
|
|
1122
1131
|
this.tfhePublicKeyDeserializer = params.tfhePublicKeyDeserializer;
|
|
1123
1132
|
if (!params.compactPkeCrsDeserializer) {
|
|
1124
|
-
throw new
|
|
1133
|
+
throw new CofheError({
|
|
1125
1134
|
code: "MISSING_COMPACT_PKE_CRS_DESERIALIZER" /* MissingCompactPkeCrsDeserializer */,
|
|
1126
1135
|
message: "EncryptInputsBuilder compactPkeCrsDeserializer is undefined",
|
|
1127
1136
|
hint: "Ensure client has been created with a compactPkeCrsDeserializer.",
|
|
@@ -1132,7 +1141,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1132
1141
|
}
|
|
1133
1142
|
this.compactPkeCrsDeserializer = params.compactPkeCrsDeserializer;
|
|
1134
1143
|
if (!params.zkBuilderAndCrsGenerator) {
|
|
1135
|
-
throw new
|
|
1144
|
+
throw new CofheError({
|
|
1136
1145
|
code: "MISSING_ZK_BUILDER_AND_CRS_GENERATOR" /* MissingZkBuilderAndCrsGenerator */,
|
|
1137
1146
|
message: "EncryptInputsBuilder zkBuilderAndCrsGenerator is undefined",
|
|
1138
1147
|
hint: "Ensure client has been created with a zkBuilderAndCrsGenerator.",
|
|
@@ -1156,7 +1165,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1156
1165
|
* ```typescript
|
|
1157
1166
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1158
1167
|
* .setAccount("0x123")
|
|
1159
|
-
* .
|
|
1168
|
+
* .execute();
|
|
1160
1169
|
* ```
|
|
1161
1170
|
*
|
|
1162
1171
|
* @returns The chainable EncryptInputsBuilder instance.
|
|
@@ -1177,7 +1186,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1177
1186
|
* ```typescript
|
|
1178
1187
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1179
1188
|
* .setChainId(11155111)
|
|
1180
|
-
* .
|
|
1189
|
+
* .execute();
|
|
1181
1190
|
* ```
|
|
1182
1191
|
*
|
|
1183
1192
|
* @returns The chainable EncryptInputsBuilder instance.
|
|
@@ -1198,7 +1207,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1198
1207
|
* ```typescript
|
|
1199
1208
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1200
1209
|
* .setSecurityZone(1)
|
|
1201
|
-
* .
|
|
1210
|
+
* .execute();
|
|
1202
1211
|
* ```
|
|
1203
1212
|
*
|
|
1204
1213
|
* @returns The chainable EncryptInputsBuilder instance.
|
|
@@ -1219,7 +1228,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1219
1228
|
* ```typescript
|
|
1220
1229
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1221
1230
|
* .setUseWorker(false)
|
|
1222
|
-
* .
|
|
1231
|
+
* .execute();
|
|
1223
1232
|
* ```
|
|
1224
1233
|
*
|
|
1225
1234
|
* @returns The chainable EncryptInputsBuilder instance.
|
|
@@ -1253,13 +1262,13 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1253
1262
|
* Example:
|
|
1254
1263
|
* ```typescript
|
|
1255
1264
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1256
|
-
* .
|
|
1257
|
-
* .
|
|
1265
|
+
* .onStep((step: EncryptStep) => console.log(step))
|
|
1266
|
+
* .execute();
|
|
1258
1267
|
* ```
|
|
1259
1268
|
*
|
|
1260
1269
|
* @returns The EncryptInputsBuilder instance.
|
|
1261
1270
|
*/
|
|
1262
|
-
|
|
1271
|
+
onStep(callback) {
|
|
1263
1272
|
this.stepCallback = callback;
|
|
1264
1273
|
return this;
|
|
1265
1274
|
}
|
|
@@ -1282,7 +1291,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1282
1291
|
this.stepCallback(step, { ...context, isStart: false, isEnd: true, duration });
|
|
1283
1292
|
}
|
|
1284
1293
|
/**
|
|
1285
|
-
* zkVerifierUrl is included in the chains exported from
|
|
1294
|
+
* zkVerifierUrl is included in the chains exported from @cofhe/sdk/chains for use in CofheConfig.supportedChains
|
|
1286
1295
|
* Users should generally not set this manually.
|
|
1287
1296
|
*/
|
|
1288
1297
|
async getZkVerifierUrl() {
|
|
@@ -1290,7 +1299,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1290
1299
|
return getZkVerifierUrlOrThrow(this.config, this.chainId);
|
|
1291
1300
|
}
|
|
1292
1301
|
/**
|
|
1293
|
-
* initTfhe is a platform-specific dependency injected into core/
|
|
1302
|
+
* initTfhe is a platform-specific dependency injected into core/createCofheClientBase by web/createCofheClient and node/createCofheClient
|
|
1294
1303
|
* web/ uses zama "tfhe"
|
|
1295
1304
|
* node/ uses zama "node-tfhe"
|
|
1296
1305
|
* Users should not set this manually.
|
|
@@ -1301,7 +1310,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1301
1310
|
try {
|
|
1302
1311
|
return await this.initTfhe();
|
|
1303
1312
|
} catch (error) {
|
|
1304
|
-
throw
|
|
1313
|
+
throw CofheError.fromError(error, {
|
|
1305
1314
|
code: "INIT_TFHE_FAILED" /* InitTfheFailed */,
|
|
1306
1315
|
message: `Failed to initialize TFHE`,
|
|
1307
1316
|
context: {
|
|
@@ -1320,7 +1329,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1320
1329
|
try {
|
|
1321
1330
|
await this.keysStorage?.rehydrateKeysStore();
|
|
1322
1331
|
} catch (error) {
|
|
1323
|
-
throw
|
|
1332
|
+
throw CofheError.fromError(error, {
|
|
1324
1333
|
code: "REHYDRATE_KEYS_STORE_FAILED" /* RehydrateKeysStoreFailed */,
|
|
1325
1334
|
message: `Failed to rehydrate keys store`,
|
|
1326
1335
|
context: {
|
|
@@ -1342,7 +1351,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1342
1351
|
this.keysStorage
|
|
1343
1352
|
);
|
|
1344
1353
|
} catch (error) {
|
|
1345
|
-
throw
|
|
1354
|
+
throw CofheError.fromError(error, {
|
|
1346
1355
|
code: "FETCH_KEYS_FAILED" /* FetchKeysFailed */,
|
|
1347
1356
|
message: `Failed to fetch FHE key and CRS`,
|
|
1348
1357
|
context: {
|
|
@@ -1355,7 +1364,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1355
1364
|
});
|
|
1356
1365
|
}
|
|
1357
1366
|
if (!fheKey) {
|
|
1358
|
-
throw new
|
|
1367
|
+
throw new CofheError({
|
|
1359
1368
|
code: "MISSING_FHE_KEY" /* MissingFheKey */,
|
|
1360
1369
|
message: `FHE key not found`,
|
|
1361
1370
|
context: {
|
|
@@ -1365,7 +1374,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1365
1374
|
});
|
|
1366
1375
|
}
|
|
1367
1376
|
if (!crs) {
|
|
1368
|
-
throw new
|
|
1377
|
+
throw new CofheError({
|
|
1369
1378
|
code: "MISSING_CRS" /* MissingCrs */,
|
|
1370
1379
|
message: `CRS not found for chainId <${this.chainId}>`,
|
|
1371
1380
|
context: {
|
|
@@ -1375,6 +1384,17 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1375
1384
|
}
|
|
1376
1385
|
return { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE };
|
|
1377
1386
|
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Resolves the encryptDelay config into an array of 5 per-step delays.
|
|
1389
|
+
* A single number is broadcast to all steps; a tuple is used as-is.
|
|
1390
|
+
*/
|
|
1391
|
+
resolveEncryptDelays() {
|
|
1392
|
+
const encryptDelay = this.config?.mocks?.encryptDelay ?? [100, 100, 100, 500, 500];
|
|
1393
|
+
if (typeof encryptDelay === "number") {
|
|
1394
|
+
return [encryptDelay, encryptDelay, encryptDelay, encryptDelay, encryptDelay];
|
|
1395
|
+
}
|
|
1396
|
+
return encryptDelay;
|
|
1397
|
+
}
|
|
1378
1398
|
/**
|
|
1379
1399
|
* @dev Encrypt against the cofheMocks instead of CoFHE
|
|
1380
1400
|
*
|
|
@@ -1382,25 +1402,35 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1382
1402
|
* cofheMocksInsertPackedHashes - stores the ctHashes and their plaintext values for on-chain mocking of FHE operations.
|
|
1383
1403
|
* cofheMocksZkCreateProofSignatures - creates signatures to be included in the encrypted inputs. The signers address is known and verified in the mock contracts.
|
|
1384
1404
|
*/
|
|
1385
|
-
async
|
|
1405
|
+
async mocksExecute() {
|
|
1386
1406
|
this.assertAccount();
|
|
1387
1407
|
this.assertPublicClient();
|
|
1388
1408
|
this.assertWalletClient();
|
|
1409
|
+
const [initTfheDelay, fetchKeysDelay, packDelay, proveDelay, verifyDelay] = this.resolveEncryptDelays();
|
|
1389
1410
|
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
1390
|
-
await sleep(
|
|
1391
|
-
this.fireStepEnd("initTfhe" /* InitTfhe */, {
|
|
1411
|
+
await sleep(initTfheDelay);
|
|
1412
|
+
this.fireStepEnd("initTfhe" /* InitTfhe */, {
|
|
1413
|
+
tfheInitializationExecuted: false,
|
|
1414
|
+
isMocks: true,
|
|
1415
|
+
mockSleep: initTfheDelay
|
|
1416
|
+
});
|
|
1392
1417
|
this.fireStepStart("fetchKeys" /* FetchKeys */);
|
|
1393
|
-
await sleep(
|
|
1394
|
-
this.fireStepEnd("fetchKeys" /* FetchKeys */, {
|
|
1418
|
+
await sleep(fetchKeysDelay);
|
|
1419
|
+
this.fireStepEnd("fetchKeys" /* FetchKeys */, {
|
|
1420
|
+
fheKeyFetchedFromCoFHE: false,
|
|
1421
|
+
crsFetchedFromCoFHE: false,
|
|
1422
|
+
isMocks: true,
|
|
1423
|
+
mockSleep: fetchKeysDelay
|
|
1424
|
+
});
|
|
1395
1425
|
this.fireStepStart("pack" /* Pack */);
|
|
1396
1426
|
await cofheMocksCheckEncryptableBits(this.inputItems);
|
|
1397
|
-
await sleep(
|
|
1398
|
-
this.fireStepEnd("pack" /* Pack
|
|
1427
|
+
await sleep(packDelay);
|
|
1428
|
+
this.fireStepEnd("pack" /* Pack */, { isMocks: true, mockSleep: packDelay });
|
|
1399
1429
|
this.fireStepStart("prove" /* Prove */);
|
|
1400
|
-
await sleep(
|
|
1401
|
-
this.fireStepEnd("prove" /* Prove
|
|
1430
|
+
await sleep(proveDelay);
|
|
1431
|
+
this.fireStepEnd("prove" /* Prove */, { isMocks: true, mockSleep: proveDelay });
|
|
1402
1432
|
this.fireStepStart("verify" /* Verify */);
|
|
1403
|
-
await sleep(
|
|
1433
|
+
await sleep(verifyDelay);
|
|
1404
1434
|
const signedResults = await cofheMocksZkVerifySign(
|
|
1405
1435
|
this.inputItems,
|
|
1406
1436
|
this.account,
|
|
@@ -1415,13 +1445,13 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1415
1445
|
utype: this.inputItems[index].utype,
|
|
1416
1446
|
signature
|
|
1417
1447
|
}));
|
|
1418
|
-
this.fireStepEnd("verify" /* Verify
|
|
1448
|
+
this.fireStepEnd("verify" /* Verify */, { isMocks: true, mockSleep: verifyDelay });
|
|
1419
1449
|
return encryptedInputs;
|
|
1420
1450
|
}
|
|
1421
1451
|
/**
|
|
1422
1452
|
* In the production context, perform a true encryption with the CoFHE coprocessor.
|
|
1423
1453
|
*/
|
|
1424
|
-
async
|
|
1454
|
+
async productionExecute() {
|
|
1425
1455
|
this.assertAccount();
|
|
1426
1456
|
this.assertChainId();
|
|
1427
1457
|
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
@@ -1484,15 +1514,15 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1484
1514
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1485
1515
|
* .setAccount('0x123...890') // optional
|
|
1486
1516
|
* .setChainId(11155111) // optional
|
|
1487
|
-
* .
|
|
1517
|
+
* .execute(); // execute
|
|
1488
1518
|
* ```
|
|
1489
1519
|
*
|
|
1490
1520
|
* @returns The encrypted inputs.
|
|
1491
1521
|
*/
|
|
1492
|
-
async
|
|
1522
|
+
async execute() {
|
|
1493
1523
|
if (this.chainId === chains.hardhat.id)
|
|
1494
|
-
return this.
|
|
1495
|
-
return this.
|
|
1524
|
+
return this.mocksExecute();
|
|
1525
|
+
return this.productionExecute();
|
|
1496
1526
|
}
|
|
1497
1527
|
};
|
|
1498
1528
|
|
|
@@ -1543,9 +1573,6 @@ function isBigIntOrNumber(value) {
|
|
|
1543
1573
|
}
|
|
1544
1574
|
}
|
|
1545
1575
|
}
|
|
1546
|
-
function is0xPrefixed(value) {
|
|
1547
|
-
return value.startsWith("0x");
|
|
1548
|
-
}
|
|
1549
1576
|
|
|
1550
1577
|
// permits/sealing.ts
|
|
1551
1578
|
var PRIVATE_KEY_LENGTH = 64;
|
|
@@ -1633,158 +1660,137 @@ var SerializedSealingPair = zod.z.object({
|
|
|
1633
1660
|
privateKey: zod.z.string(),
|
|
1634
1661
|
publicKey: zod.z.string()
|
|
1635
1662
|
});
|
|
1663
|
+
var addressSchema = zod.z.string().refine((val) => viem.isAddress(val), {
|
|
1664
|
+
error: "Invalid address"
|
|
1665
|
+
}).transform((val) => viem.getAddress(val));
|
|
1666
|
+
var addressNotZeroSchema = addressSchema.refine((val) => val !== viem.zeroAddress, {
|
|
1667
|
+
error: "Must not be zeroAddress"
|
|
1668
|
+
});
|
|
1669
|
+
var bytesSchema = zod.z.custom(
|
|
1670
|
+
(val) => {
|
|
1671
|
+
return typeof val === "string" && viem.isHex(val);
|
|
1672
|
+
},
|
|
1673
|
+
{
|
|
1674
|
+
message: "Invalid hex value"
|
|
1675
|
+
}
|
|
1676
|
+
);
|
|
1677
|
+
var bytesNotEmptySchema = bytesSchema.refine((val) => val !== "0x", {
|
|
1678
|
+
error: "Must not be empty"
|
|
1679
|
+
});
|
|
1636
1680
|
var DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1e3) + 7 * 24 * 60 * 60;
|
|
1637
1681
|
var zPermitWithDefaults = zod.z.object({
|
|
1638
1682
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
1639
1683
|
type: zod.z.enum(["self", "sharing", "recipient"]),
|
|
1640
|
-
issuer:
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
message: "Permit recipient :: invalid address"
|
|
1648
|
-
}),
|
|
1649
|
-
validatorId: zod.z.number().optional().default(0),
|
|
1650
|
-
validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
|
|
1651
|
-
message: "Permit validatorContract :: invalid address"
|
|
1652
|
-
}),
|
|
1653
|
-
issuerSignature: zod.z.string().optional().default("0x"),
|
|
1654
|
-
recipientSignature: zod.z.string().optional().default("0x")
|
|
1684
|
+
issuer: addressNotZeroSchema,
|
|
1685
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1686
|
+
recipient: addressSchema.optional().default(viem.zeroAddress),
|
|
1687
|
+
validatorId: zod.z.int().optional().default(0),
|
|
1688
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1689
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1690
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
1655
1691
|
});
|
|
1656
1692
|
var zPermitWithSealingPair = zPermitWithDefaults.extend({
|
|
1657
1693
|
sealingPair: SerializedSealingPair.optional()
|
|
1658
1694
|
});
|
|
1659
|
-
var
|
|
1695
|
+
var ExternalValidatorRefinement = [
|
|
1660
1696
|
(data) => data.validatorId !== 0 && data.validatorContract !== viem.zeroAddress || data.validatorId === 0 && data.validatorContract === viem.zeroAddress,
|
|
1661
1697
|
{
|
|
1662
|
-
|
|
1698
|
+
error: "Permit external validator :: validatorId and validatorContract must either both be set or both be unset.",
|
|
1663
1699
|
path: ["validatorId", "validatorContract"]
|
|
1664
1700
|
}
|
|
1665
1701
|
];
|
|
1702
|
+
var RecipientRefinement = [
|
|
1703
|
+
(data) => data.issuer !== data.recipient,
|
|
1704
|
+
{
|
|
1705
|
+
error: "Sharing permit :: issuer and recipient must not be the same",
|
|
1706
|
+
path: ["issuer", "recipient"]
|
|
1707
|
+
}
|
|
1708
|
+
];
|
|
1666
1709
|
var SelfPermitOptionsValidator = zod.z.object({
|
|
1667
1710
|
type: zod.z.literal("self").optional().default("self"),
|
|
1668
|
-
issuer:
|
|
1669
|
-
message: "Self permit issuer :: invalid address"
|
|
1670
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1671
|
-
message: "Self permit issuer :: must be 0x prefixed"
|
|
1672
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1673
|
-
message: "Self permit issuer :: must not be zeroAddress"
|
|
1674
|
-
}),
|
|
1711
|
+
issuer: addressNotZeroSchema,
|
|
1675
1712
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
1676
|
-
expiration: zod.z.
|
|
1677
|
-
recipient:
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
}),
|
|
1684
|
-
validatorId: zod.z.number().optional().default(0),
|
|
1685
|
-
validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
|
|
1686
|
-
message: "Self permit validatorContract :: invalid address"
|
|
1687
|
-
}),
|
|
1688
|
-
issuerSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
1689
|
-
message: "Self permit issuerSignature :: must be 0x prefixed"
|
|
1690
|
-
}),
|
|
1691
|
-
recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
1692
|
-
message: "Self permit recipientSignature :: must be 0x prefixed"
|
|
1693
|
-
})
|
|
1694
|
-
}).refine(...ValidatorContractRefinement);
|
|
1713
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1714
|
+
recipient: addressSchema.optional().default(viem.zeroAddress),
|
|
1715
|
+
validatorId: zod.z.int().optional().default(0),
|
|
1716
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1717
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1718
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
1719
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1695
1720
|
var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "self", {
|
|
1696
|
-
|
|
1721
|
+
error: "Type must be 'self'"
|
|
1697
1722
|
}).refine((data) => data.recipient === viem.zeroAddress, {
|
|
1698
|
-
|
|
1723
|
+
error: "Recipient must be zeroAddress"
|
|
1699
1724
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
1700
|
-
|
|
1725
|
+
error: "IssuerSignature must be populated"
|
|
1701
1726
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
1702
|
-
|
|
1703
|
-
}).refine(...
|
|
1727
|
+
error: "RecipientSignature must be empty"
|
|
1728
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1704
1729
|
var SharingPermitOptionsValidator = zod.z.object({
|
|
1705
1730
|
type: zod.z.literal("sharing").optional().default("sharing"),
|
|
1706
|
-
issuer:
|
|
1707
|
-
|
|
1708
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1709
|
-
message: "Sharing permit issuer :: must be 0x prefixed"
|
|
1710
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1711
|
-
message: "Sharing permit issuer :: must not be zeroAddress"
|
|
1712
|
-
}),
|
|
1713
|
-
recipient: zod.z.string().refine((val) => viem.isAddress(val), {
|
|
1714
|
-
message: "Sharing permit recipient :: invalid address"
|
|
1715
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1716
|
-
message: "Sharing permit recipient :: must be 0x prefixed"
|
|
1717
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1718
|
-
message: "Sharing permit recipient :: must not be zeroAddress"
|
|
1719
|
-
}),
|
|
1731
|
+
issuer: addressNotZeroSchema,
|
|
1732
|
+
recipient: addressNotZeroSchema,
|
|
1720
1733
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
1721
|
-
expiration: zod.z.
|
|
1722
|
-
validatorId: zod.z.
|
|
1723
|
-
validatorContract:
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
message: "Sharing permit issuerSignature :: must be 0x prefixed"
|
|
1728
|
-
}),
|
|
1729
|
-
recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
1730
|
-
message: "Sharing permit recipientSignature :: must be 0x prefixed"
|
|
1731
|
-
})
|
|
1732
|
-
}).refine(...ValidatorContractRefinement);
|
|
1734
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1735
|
+
validatorId: zod.z.int().optional().default(0),
|
|
1736
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1737
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1738
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
1739
|
+
}).refine(...RecipientRefinement).refine(...ExternalValidatorRefinement);
|
|
1733
1740
|
var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "sharing", {
|
|
1734
|
-
|
|
1741
|
+
error: "Type must be 'sharing'"
|
|
1735
1742
|
}).refine((data) => data.recipient !== viem.zeroAddress, {
|
|
1736
|
-
|
|
1743
|
+
error: "Recipient must not be zeroAddress"
|
|
1737
1744
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
1738
|
-
|
|
1745
|
+
error: "IssuerSignature must be populated"
|
|
1739
1746
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
1740
|
-
|
|
1741
|
-
}).refine(...
|
|
1747
|
+
error: "RecipientSignature must be empty"
|
|
1748
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1742
1749
|
var ImportPermitOptionsValidator = zod.z.object({
|
|
1743
1750
|
type: zod.z.literal("recipient").optional().default("recipient"),
|
|
1744
|
-
issuer:
|
|
1745
|
-
|
|
1746
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1747
|
-
message: "Import permit issuer :: must be 0x prefixed"
|
|
1748
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1749
|
-
message: "Import permit issuer :: must not be zeroAddress"
|
|
1750
|
-
}),
|
|
1751
|
-
recipient: zod.z.string().refine((val) => viem.isAddress(val), {
|
|
1752
|
-
message: "Import permit recipient :: invalid address"
|
|
1753
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1754
|
-
message: "Import permit recipient :: must be 0x prefixed"
|
|
1755
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1756
|
-
message: "Import permit recipient :: must not be zeroAddress"
|
|
1757
|
-
}),
|
|
1758
|
-
issuerSignature: zod.z.string().refine((val) => is0xPrefixed(val), {
|
|
1759
|
-
message: "Import permit issuerSignature :: must be 0x prefixed"
|
|
1760
|
-
}).refine((val) => val !== "0x", {
|
|
1761
|
-
message: "Import permit :: issuerSignature must be provided"
|
|
1762
|
-
}),
|
|
1751
|
+
issuer: addressNotZeroSchema,
|
|
1752
|
+
recipient: addressNotZeroSchema,
|
|
1763
1753
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
1764
|
-
expiration: zod.z.
|
|
1765
|
-
validatorId: zod.z.
|
|
1766
|
-
validatorContract:
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
message: "Import permit recipientSignature :: must be 0x prefixed"
|
|
1771
|
-
})
|
|
1772
|
-
}).refine(...ValidatorContractRefinement);
|
|
1754
|
+
expiration: zod.z.int(),
|
|
1755
|
+
validatorId: zod.z.int().optional().default(0),
|
|
1756
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1757
|
+
issuerSignature: bytesNotEmptySchema,
|
|
1758
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
1759
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1773
1760
|
var ImportPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "recipient", {
|
|
1774
|
-
|
|
1761
|
+
error: "Type must be 'recipient'"
|
|
1775
1762
|
}).refine((data) => data.recipient !== viem.zeroAddress, {
|
|
1776
|
-
|
|
1763
|
+
error: "Recipient must not be zeroAddress"
|
|
1777
1764
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
1778
|
-
|
|
1765
|
+
error: "IssuerSignature must be populated"
|
|
1779
1766
|
}).refine((data) => data.recipientSignature !== "0x", {
|
|
1780
|
-
|
|
1781
|
-
}).refine(...
|
|
1782
|
-
var
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1767
|
+
error: "RecipientSignature must be populated"
|
|
1768
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1769
|
+
var safeParseAndThrowFormatted = (schema, data, message) => {
|
|
1770
|
+
const result = schema.safeParse(data);
|
|
1771
|
+
if (!result.success) {
|
|
1772
|
+
throw new Error(`${message}: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
|
|
1773
|
+
}
|
|
1774
|
+
return result.data;
|
|
1775
|
+
};
|
|
1776
|
+
var validateSelfPermitOptions = (options) => {
|
|
1777
|
+
return safeParseAndThrowFormatted(SelfPermitOptionsValidator, options, "Invalid self permit options");
|
|
1778
|
+
};
|
|
1779
|
+
var validateSharingPermitOptions = (options) => {
|
|
1780
|
+
return safeParseAndThrowFormatted(SharingPermitOptionsValidator, options, "Invalid sharing permit options");
|
|
1781
|
+
};
|
|
1782
|
+
var validateImportPermitOptions = (options) => {
|
|
1783
|
+
return safeParseAndThrowFormatted(ImportPermitOptionsValidator, options, "Invalid import permit options");
|
|
1784
|
+
};
|
|
1785
|
+
var validateSelfPermit = (permit) => {
|
|
1786
|
+
return safeParseAndThrowFormatted(SelfPermitValidator, permit, "Invalid self permit");
|
|
1787
|
+
};
|
|
1788
|
+
var validateSharingPermit = (permit) => {
|
|
1789
|
+
return safeParseAndThrowFormatted(SharingPermitValidator, permit, "Invalid sharing permit");
|
|
1790
|
+
};
|
|
1791
|
+
var validateImportPermit = (permit) => {
|
|
1792
|
+
return safeParseAndThrowFormatted(ImportPermitValidator, permit, "Invalid import permit");
|
|
1793
|
+
};
|
|
1788
1794
|
var ValidationUtils = {
|
|
1789
1795
|
/**
|
|
1790
1796
|
* Check if permit is expired
|
|
@@ -1878,6 +1884,179 @@ var SignatureUtils = {
|
|
|
1878
1884
|
throw new Error(`Unknown permit type: ${permitType}`);
|
|
1879
1885
|
}
|
|
1880
1886
|
};
|
|
1887
|
+
var getAclAddress = async (publicClient) => {
|
|
1888
|
+
const ACL_IFACE = "function acl() view returns (address)";
|
|
1889
|
+
const aclAbi = viem.parseAbi([ACL_IFACE]);
|
|
1890
|
+
return await publicClient.readContract({
|
|
1891
|
+
address: TASK_MANAGER_ADDRESS,
|
|
1892
|
+
abi: aclAbi,
|
|
1893
|
+
functionName: "acl"
|
|
1894
|
+
});
|
|
1895
|
+
};
|
|
1896
|
+
var getAclEIP712Domain = async (publicClient) => {
|
|
1897
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
1898
|
+
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
1899
|
+
const domainAbi = viem.parseAbi([EIP712_DOMAIN_IFACE]);
|
|
1900
|
+
const domain = await publicClient.readContract({
|
|
1901
|
+
address: aclAddress,
|
|
1902
|
+
abi: domainAbi,
|
|
1903
|
+
functionName: "eip712Domain"
|
|
1904
|
+
});
|
|
1905
|
+
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
1906
|
+
return {
|
|
1907
|
+
name,
|
|
1908
|
+
version,
|
|
1909
|
+
chainId: Number(chainId),
|
|
1910
|
+
verifyingContract
|
|
1911
|
+
};
|
|
1912
|
+
};
|
|
1913
|
+
var checkPermitValidityOnChain = async (permission, publicClient) => {
|
|
1914
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
1915
|
+
try {
|
|
1916
|
+
await publicClient.simulateContract({
|
|
1917
|
+
address: aclAddress,
|
|
1918
|
+
abi: checkPermitValidityAbi,
|
|
1919
|
+
functionName: "checkPermitValidity",
|
|
1920
|
+
args: [
|
|
1921
|
+
{
|
|
1922
|
+
issuer: permission.issuer,
|
|
1923
|
+
expiration: BigInt(permission.expiration),
|
|
1924
|
+
recipient: permission.recipient,
|
|
1925
|
+
validatorId: BigInt(permission.validatorId),
|
|
1926
|
+
validatorContract: permission.validatorContract,
|
|
1927
|
+
sealingKey: permission.sealingKey,
|
|
1928
|
+
issuerSignature: permission.issuerSignature,
|
|
1929
|
+
recipientSignature: permission.recipientSignature
|
|
1930
|
+
}
|
|
1931
|
+
]
|
|
1932
|
+
});
|
|
1933
|
+
return true;
|
|
1934
|
+
} catch (err) {
|
|
1935
|
+
if (err instanceof viem.BaseError) {
|
|
1936
|
+
const revertError = err.walk((err2) => err2 instanceof viem.ContractFunctionRevertedError);
|
|
1937
|
+
if (revertError instanceof viem.ContractFunctionRevertedError) {
|
|
1938
|
+
const errorName = revertError.data?.errorName ?? "";
|
|
1939
|
+
throw new Error(errorName);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
const customErrorName = extractCustomErrorFromDetails(err, checkPermitValidityAbi);
|
|
1943
|
+
if (customErrorName) {
|
|
1944
|
+
throw new Error(customErrorName);
|
|
1945
|
+
}
|
|
1946
|
+
const hhDetailsData = extractReturnData(err);
|
|
1947
|
+
if (hhDetailsData != null) {
|
|
1948
|
+
const decoded = viem.decodeErrorResult({
|
|
1949
|
+
abi: checkPermitValidityAbi,
|
|
1950
|
+
data: hhDetailsData
|
|
1951
|
+
});
|
|
1952
|
+
throw new Error(decoded.errorName);
|
|
1953
|
+
}
|
|
1954
|
+
throw err;
|
|
1955
|
+
}
|
|
1956
|
+
};
|
|
1957
|
+
function extractCustomErrorFromDetails(err, abi) {
|
|
1958
|
+
const anyErr = err;
|
|
1959
|
+
const details = anyErr?.details ?? anyErr?.cause?.details;
|
|
1960
|
+
if (typeof details === "string") {
|
|
1961
|
+
const customErrorMatch = details.match(/reverted with custom error '(\w+)\(\)'/);
|
|
1962
|
+
if (customErrorMatch) {
|
|
1963
|
+
const errorName = customErrorMatch[1];
|
|
1964
|
+
const errorExists = abi.some((item) => item.type === "error" && item.name === errorName);
|
|
1965
|
+
if (errorExists) {
|
|
1966
|
+
return errorName;
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
return void 0;
|
|
1971
|
+
}
|
|
1972
|
+
function extractReturnData(err) {
|
|
1973
|
+
const anyErr = err;
|
|
1974
|
+
const s = anyErr?.details ?? anyErr?.cause?.details ?? anyErr?.shortMessage ?? anyErr?.message ?? String(err);
|
|
1975
|
+
return s.match(/return data:\s*(0x[a-fA-F0-9]+)/)?.[1];
|
|
1976
|
+
}
|
|
1977
|
+
var checkPermitValidityAbi = [
|
|
1978
|
+
{
|
|
1979
|
+
type: "function",
|
|
1980
|
+
name: "checkPermitValidity",
|
|
1981
|
+
inputs: [
|
|
1982
|
+
{
|
|
1983
|
+
name: "permission",
|
|
1984
|
+
type: "tuple",
|
|
1985
|
+
internalType: "struct Permission",
|
|
1986
|
+
components: [
|
|
1987
|
+
{
|
|
1988
|
+
name: "issuer",
|
|
1989
|
+
type: "address",
|
|
1990
|
+
internalType: "address"
|
|
1991
|
+
},
|
|
1992
|
+
{
|
|
1993
|
+
name: "expiration",
|
|
1994
|
+
type: "uint64",
|
|
1995
|
+
internalType: "uint64"
|
|
1996
|
+
},
|
|
1997
|
+
{
|
|
1998
|
+
name: "recipient",
|
|
1999
|
+
type: "address",
|
|
2000
|
+
internalType: "address"
|
|
2001
|
+
},
|
|
2002
|
+
{
|
|
2003
|
+
name: "validatorId",
|
|
2004
|
+
type: "uint256",
|
|
2005
|
+
internalType: "uint256"
|
|
2006
|
+
},
|
|
2007
|
+
{
|
|
2008
|
+
name: "validatorContract",
|
|
2009
|
+
type: "address",
|
|
2010
|
+
internalType: "address"
|
|
2011
|
+
},
|
|
2012
|
+
{
|
|
2013
|
+
name: "sealingKey",
|
|
2014
|
+
type: "bytes32",
|
|
2015
|
+
internalType: "bytes32"
|
|
2016
|
+
},
|
|
2017
|
+
{
|
|
2018
|
+
name: "issuerSignature",
|
|
2019
|
+
type: "bytes",
|
|
2020
|
+
internalType: "bytes"
|
|
2021
|
+
},
|
|
2022
|
+
{
|
|
2023
|
+
name: "recipientSignature",
|
|
2024
|
+
type: "bytes",
|
|
2025
|
+
internalType: "bytes"
|
|
2026
|
+
}
|
|
2027
|
+
]
|
|
2028
|
+
}
|
|
2029
|
+
],
|
|
2030
|
+
outputs: [
|
|
2031
|
+
{
|
|
2032
|
+
name: "",
|
|
2033
|
+
type: "bool",
|
|
2034
|
+
internalType: "bool"
|
|
2035
|
+
}
|
|
2036
|
+
],
|
|
2037
|
+
stateMutability: "view"
|
|
2038
|
+
},
|
|
2039
|
+
{
|
|
2040
|
+
type: "error",
|
|
2041
|
+
name: "PermissionInvalid_Disabled",
|
|
2042
|
+
inputs: []
|
|
2043
|
+
},
|
|
2044
|
+
{
|
|
2045
|
+
type: "error",
|
|
2046
|
+
name: "PermissionInvalid_Expired",
|
|
2047
|
+
inputs: []
|
|
2048
|
+
},
|
|
2049
|
+
{
|
|
2050
|
+
type: "error",
|
|
2051
|
+
name: "PermissionInvalid_IssuerSignature",
|
|
2052
|
+
inputs: []
|
|
2053
|
+
},
|
|
2054
|
+
{
|
|
2055
|
+
type: "error",
|
|
2056
|
+
name: "PermissionInvalid_RecipientSignature",
|
|
2057
|
+
inputs: []
|
|
2058
|
+
}
|
|
2059
|
+
];
|
|
1881
2060
|
|
|
1882
2061
|
// permits/permit.ts
|
|
1883
2062
|
var PermitUtils = {
|
|
@@ -1886,14 +2065,10 @@ var PermitUtils = {
|
|
|
1886
2065
|
*/
|
|
1887
2066
|
createSelf: (options) => {
|
|
1888
2067
|
const validation = validateSelfPermitOptions(options);
|
|
1889
|
-
if (!validation.success) {
|
|
1890
|
-
throw new Error(
|
|
1891
|
-
"PermitUtils :: createSelf :: Parsing SelfPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
1892
|
-
);
|
|
1893
|
-
}
|
|
1894
2068
|
const sealingPair = GenerateSealingKey();
|
|
1895
2069
|
const permit = {
|
|
1896
|
-
|
|
2070
|
+
hash: PermitUtils.getHash(validation),
|
|
2071
|
+
...validation,
|
|
1897
2072
|
sealingPair,
|
|
1898
2073
|
_signedDomain: void 0
|
|
1899
2074
|
};
|
|
@@ -1904,14 +2079,10 @@ var PermitUtils = {
|
|
|
1904
2079
|
*/
|
|
1905
2080
|
createSharing: (options) => {
|
|
1906
2081
|
const validation = validateSharingPermitOptions(options);
|
|
1907
|
-
if (!validation.success) {
|
|
1908
|
-
throw new Error(
|
|
1909
|
-
"PermitUtils :: createSharing :: Parsing SharingPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
1910
|
-
);
|
|
1911
|
-
}
|
|
1912
2082
|
const sealingPair = GenerateSealingKey();
|
|
1913
2083
|
const permit = {
|
|
1914
|
-
|
|
2084
|
+
hash: PermitUtils.getHash(validation),
|
|
2085
|
+
...validation,
|
|
1915
2086
|
sealingPair,
|
|
1916
2087
|
_signedDomain: void 0
|
|
1917
2088
|
};
|
|
@@ -1926,27 +2097,21 @@ var PermitUtils = {
|
|
|
1926
2097
|
try {
|
|
1927
2098
|
parsedOptions = JSON.parse(options);
|
|
1928
2099
|
} catch (error) {
|
|
1929
|
-
throw new Error(`
|
|
2100
|
+
throw new Error(`Failed to parse JSON string: ${error}`);
|
|
1930
2101
|
}
|
|
1931
2102
|
} else if (typeof options === "object" && options !== null) {
|
|
1932
2103
|
parsedOptions = options;
|
|
1933
2104
|
} else {
|
|
1934
|
-
throw new Error(
|
|
1935
|
-
"PermitUtils :: importShared :: Invalid input type, expected ImportSharedPermitOptions, object, or string"
|
|
1936
|
-
);
|
|
2105
|
+
throw new Error("Invalid input type, expected ImportSharedPermitOptions, object, or string");
|
|
1937
2106
|
}
|
|
1938
2107
|
if (parsedOptions.type != null && parsedOptions.type !== "sharing") {
|
|
1939
|
-
throw new Error(`
|
|
2108
|
+
throw new Error(`Invalid permit type <${parsedOptions.type}>, must be "sharing"`);
|
|
1940
2109
|
}
|
|
1941
2110
|
const validation = validateImportPermitOptions({ ...parsedOptions, type: "recipient" });
|
|
1942
|
-
if (!validation.success) {
|
|
1943
|
-
throw new Error(
|
|
1944
|
-
"PermitUtils :: importShared :: Parsing ImportPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
1945
|
-
);
|
|
1946
|
-
}
|
|
1947
2111
|
const sealingPair = GenerateSealingKey();
|
|
1948
2112
|
const permit = {
|
|
1949
|
-
|
|
2113
|
+
hash: PermitUtils.getHash(validation),
|
|
2114
|
+
...validation,
|
|
1950
2115
|
sealingPair,
|
|
1951
2116
|
_signedDomain: void 0
|
|
1952
2117
|
};
|
|
@@ -1958,11 +2123,11 @@ var PermitUtils = {
|
|
|
1958
2123
|
sign: async (permit, publicClient, walletClient) => {
|
|
1959
2124
|
if (walletClient == null || walletClient.account == null) {
|
|
1960
2125
|
throw new Error(
|
|
1961
|
-
"
|
|
2126
|
+
"Missing walletClient, you must pass in a `walletClient` for the connected user to create a permit signature"
|
|
1962
2127
|
);
|
|
1963
2128
|
}
|
|
1964
2129
|
const primaryType = SignatureUtils.getPrimaryType(permit.type);
|
|
1965
|
-
const domain = await
|
|
2130
|
+
const domain = await getAclEIP712Domain(publicClient);
|
|
1966
2131
|
const { types, message } = SignatureUtils.getSignatureParams(PermitUtils.getPermission(permit, true), primaryType);
|
|
1967
2132
|
const signature = await walletClient.signTypedData({
|
|
1968
2133
|
domain,
|
|
@@ -2022,6 +2187,7 @@ var PermitUtils = {
|
|
|
2022
2187
|
*/
|
|
2023
2188
|
serialize: (permit) => {
|
|
2024
2189
|
return {
|
|
2190
|
+
hash: permit.hash,
|
|
2025
2191
|
name: permit.name,
|
|
2026
2192
|
type: permit.type,
|
|
2027
2193
|
issuer: permit.issuer,
|
|
@@ -2046,7 +2212,7 @@ var PermitUtils = {
|
|
|
2046
2212
|
} else if (permit.type === "recipient") {
|
|
2047
2213
|
return validateImportPermit(permit);
|
|
2048
2214
|
} else {
|
|
2049
|
-
throw new Error("
|
|
2215
|
+
throw new Error("Invalid permit type");
|
|
2050
2216
|
}
|
|
2051
2217
|
},
|
|
2052
2218
|
/**
|
|
@@ -2054,12 +2220,7 @@ var PermitUtils = {
|
|
|
2054
2220
|
*/
|
|
2055
2221
|
getPermission: (permit, skipValidation = false) => {
|
|
2056
2222
|
if (!skipValidation) {
|
|
2057
|
-
|
|
2058
|
-
if (!validationResult.success) {
|
|
2059
|
-
throw new Error(
|
|
2060
|
-
`PermitUtils :: getPermission :: permit validation failed - ${JSON.stringify(validationResult.error, null, 2)} ${JSON.stringify(permit, null, 2)}`
|
|
2061
|
-
);
|
|
2062
|
-
}
|
|
2223
|
+
PermitUtils.validate(permit);
|
|
2063
2224
|
}
|
|
2064
2225
|
return {
|
|
2065
2226
|
issuer: permit.issuer,
|
|
@@ -2140,28 +2301,7 @@ var PermitUtils = {
|
|
|
2140
2301
|
* Fetch EIP712 domain from the blockchain
|
|
2141
2302
|
*/
|
|
2142
2303
|
fetchEIP712Domain: async (publicClient) => {
|
|
2143
|
-
|
|
2144
|
-
const ACL_IFACE = "function acl() view returns (address)";
|
|
2145
|
-
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
2146
|
-
const aclAbi = viem.parseAbi([ACL_IFACE]);
|
|
2147
|
-
const aclAddress = await publicClient.readContract({
|
|
2148
|
-
address: TASK_MANAGER_ADDRESS,
|
|
2149
|
-
abi: aclAbi,
|
|
2150
|
-
functionName: "acl"
|
|
2151
|
-
});
|
|
2152
|
-
const domainAbi = viem.parseAbi([EIP712_DOMAIN_IFACE]);
|
|
2153
|
-
const domain = await publicClient.readContract({
|
|
2154
|
-
address: aclAddress,
|
|
2155
|
-
abi: domainAbi,
|
|
2156
|
-
functionName: "eip712Domain"
|
|
2157
|
-
});
|
|
2158
|
-
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
2159
|
-
return {
|
|
2160
|
-
name,
|
|
2161
|
-
version,
|
|
2162
|
-
chainId: Number(chainId),
|
|
2163
|
-
verifyingContract
|
|
2164
|
-
};
|
|
2304
|
+
return getAclEIP712Domain(publicClient);
|
|
2165
2305
|
},
|
|
2166
2306
|
/**
|
|
2167
2307
|
* Check if permit's signed domain matches the provided domain
|
|
@@ -2175,8 +2315,15 @@ var PermitUtils = {
|
|
|
2175
2315
|
checkSignedDomainValid: async (permit, publicClient) => {
|
|
2176
2316
|
if (permit._signedDomain == null)
|
|
2177
2317
|
return false;
|
|
2178
|
-
const domain = await
|
|
2318
|
+
const domain = await getAclEIP712Domain(publicClient);
|
|
2179
2319
|
return PermitUtils.matchesDomain(permit, domain);
|
|
2320
|
+
},
|
|
2321
|
+
/**
|
|
2322
|
+
* Check if permit passes the on-chain validation
|
|
2323
|
+
*/
|
|
2324
|
+
checkValidityOnChain: async (permit, publicClient) => {
|
|
2325
|
+
const permission = PermitUtils.getPermission(permit);
|
|
2326
|
+
return checkPermitValidityOnChain(permission, publicClient);
|
|
2180
2327
|
}
|
|
2181
2328
|
};
|
|
2182
2329
|
var PERMIT_STORE_DEFAULTS = {
|
|
@@ -2230,11 +2377,11 @@ var setPermit = (chainId, account, permit) => {
|
|
|
2230
2377
|
state.permits[chainId] = {};
|
|
2231
2378
|
if (state.permits[chainId][account] == null)
|
|
2232
2379
|
state.permits[chainId][account] = {};
|
|
2233
|
-
state.permits[chainId][account][
|
|
2380
|
+
state.permits[chainId][account][permit.hash] = PermitUtils.serialize(permit);
|
|
2234
2381
|
})
|
|
2235
2382
|
);
|
|
2236
2383
|
};
|
|
2237
|
-
var removePermit = (chainId, account, hash
|
|
2384
|
+
var removePermit = (chainId, account, hash) => {
|
|
2238
2385
|
clearStaleStore();
|
|
2239
2386
|
_permitStore.setState(
|
|
2240
2387
|
immer.produce((state) => {
|
|
@@ -2248,15 +2395,7 @@ var removePermit = (chainId, account, hash, force) => {
|
|
|
2248
2395
|
if (accountPermits[hash] == null)
|
|
2249
2396
|
return;
|
|
2250
2397
|
if (state.activePermitHash[chainId][account] === hash) {
|
|
2251
|
-
|
|
2252
|
-
if (otherPermitHash) {
|
|
2253
|
-
state.activePermitHash[chainId][account] = otherPermitHash;
|
|
2254
|
-
} else {
|
|
2255
|
-
if (!force) {
|
|
2256
|
-
throw new Error("Cannot remove the last permit without force flag");
|
|
2257
|
-
}
|
|
2258
|
-
state.activePermitHash[chainId][account] = void 0;
|
|
2259
|
-
}
|
|
2398
|
+
state.activePermitHash[chainId][account] = void 0;
|
|
2260
2399
|
}
|
|
2261
2400
|
accountPermits[hash] = void 0;
|
|
2262
2401
|
})
|
|
@@ -2307,7 +2446,7 @@ var storeActivePermit = async (permit, publicClient, walletClient) => {
|
|
|
2307
2446
|
const chainId = await publicClient.getChainId();
|
|
2308
2447
|
const account = walletClient.account.address;
|
|
2309
2448
|
permitStore.setPermit(chainId, account, permit);
|
|
2310
|
-
permitStore.setActivePermitHash(chainId, account,
|
|
2449
|
+
permitStore.setActivePermitHash(chainId, account, permit.hash);
|
|
2311
2450
|
};
|
|
2312
2451
|
var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
|
|
2313
2452
|
const permit = await permitMethod(options, publicClient, walletClient);
|
|
@@ -2365,7 +2504,7 @@ var getOrCreateSharingPermit = async (publicClient, walletClient, options, chain
|
|
|
2365
2504
|
}
|
|
2366
2505
|
return createSharing(options, publicClient, walletClient);
|
|
2367
2506
|
};
|
|
2368
|
-
var removePermit2 = async (chainId, account, hash
|
|
2507
|
+
var removePermit2 = async (chainId, account, hash) => permitStore.removePermit(chainId, account, hash);
|
|
2369
2508
|
var removeActivePermit = async (chainId, account) => permitStore.removeActivePermitHash(chainId, account);
|
|
2370
2509
|
var permits = {
|
|
2371
2510
|
getSnapshot: permitStore.store.getState,
|
|
@@ -2405,8 +2544,8 @@ var convertViaUtype = (utype, value) => {
|
|
|
2405
2544
|
}
|
|
2406
2545
|
};
|
|
2407
2546
|
|
|
2408
|
-
// core/decrypt/
|
|
2409
|
-
var
|
|
2547
|
+
// core/decrypt/MockThresholdNetworkAbi.ts
|
|
2548
|
+
var MockThresholdNetworkAbi = [
|
|
2410
2549
|
{
|
|
2411
2550
|
type: "function",
|
|
2412
2551
|
name: "acl",
|
|
@@ -2453,11 +2592,7 @@ var MockQueryDecrypterAbi = [
|
|
|
2453
2592
|
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2454
2593
|
{ name: "recipient", type: "address", internalType: "address" },
|
|
2455
2594
|
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
2456
|
-
{
|
|
2457
|
-
name: "validatorContract",
|
|
2458
|
-
type: "address",
|
|
2459
|
-
internalType: "address"
|
|
2460
|
-
},
|
|
2595
|
+
{ name: "validatorContract", type: "address", internalType: "address" },
|
|
2461
2596
|
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2462
2597
|
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2463
2598
|
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
@@ -2486,11 +2621,7 @@ var MockQueryDecrypterAbi = [
|
|
|
2486
2621
|
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2487
2622
|
{ name: "recipient", type: "address", internalType: "address" },
|
|
2488
2623
|
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
2489
|
-
{
|
|
2490
|
-
name: "validatorContract",
|
|
2491
|
-
type: "address",
|
|
2492
|
-
internalType: "address"
|
|
2493
|
-
},
|
|
2624
|
+
{ name: "validatorContract", type: "address", internalType: "address" },
|
|
2494
2625
|
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2495
2626
|
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2496
2627
|
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
@@ -2514,13 +2645,6 @@ var MockQueryDecrypterAbi = [
|
|
|
2514
2645
|
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
2515
2646
|
stateMutability: "pure"
|
|
2516
2647
|
},
|
|
2517
|
-
{
|
|
2518
|
-
type: "function",
|
|
2519
|
-
name: "taskManager",
|
|
2520
|
-
inputs: [],
|
|
2521
|
-
outputs: [{ name: "", type: "address", internalType: "contract TaskManager" }],
|
|
2522
|
-
stateMutability: "view"
|
|
2523
|
-
},
|
|
2524
2648
|
{
|
|
2525
2649
|
type: "function",
|
|
2526
2650
|
name: "unseal",
|
|
@@ -2531,16 +2655,80 @@ var MockQueryDecrypterAbi = [
|
|
|
2531
2655
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
2532
2656
|
stateMutability: "pure"
|
|
2533
2657
|
},
|
|
2534
|
-
{
|
|
2535
|
-
|
|
2536
|
-
|
|
2658
|
+
{
|
|
2659
|
+
type: "function",
|
|
2660
|
+
name: "mockAcl",
|
|
2661
|
+
inputs: [],
|
|
2662
|
+
outputs: [{ name: "", type: "address", internalType: "contract MockACL" }],
|
|
2663
|
+
stateMutability: "view"
|
|
2664
|
+
},
|
|
2665
|
+
{
|
|
2666
|
+
type: "function",
|
|
2667
|
+
name: "mockTaskManager",
|
|
2668
|
+
inputs: [],
|
|
2669
|
+
outputs: [{ name: "", type: "address", internalType: "contract MockTaskManager" }],
|
|
2670
|
+
stateMutability: "view"
|
|
2671
|
+
},
|
|
2672
|
+
{
|
|
2673
|
+
type: "function",
|
|
2674
|
+
name: "mockQueryDecrypt",
|
|
2675
|
+
inputs: [
|
|
2676
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
2677
|
+
{ name: "", type: "uint256", internalType: "uint256" },
|
|
2678
|
+
{ name: "issuer", type: "address", internalType: "address" }
|
|
2679
|
+
],
|
|
2680
|
+
outputs: [
|
|
2681
|
+
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
2682
|
+
{ name: "error", type: "string", internalType: "string" },
|
|
2683
|
+
{ name: "", type: "uint256", internalType: "uint256" }
|
|
2684
|
+
],
|
|
2685
|
+
stateMutability: "view"
|
|
2686
|
+
},
|
|
2687
|
+
{
|
|
2688
|
+
type: "function",
|
|
2689
|
+
name: "decryptForTxWithPermit",
|
|
2690
|
+
inputs: [
|
|
2691
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
2692
|
+
{
|
|
2693
|
+
name: "permission",
|
|
2694
|
+
type: "tuple",
|
|
2695
|
+
internalType: "struct Permission",
|
|
2696
|
+
components: [
|
|
2697
|
+
{ name: "issuer", type: "address", internalType: "address" },
|
|
2698
|
+
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2699
|
+
{ name: "recipient", type: "address", internalType: "address" },
|
|
2700
|
+
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
2701
|
+
{ name: "validatorContract", type: "address", internalType: "address" },
|
|
2702
|
+
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2703
|
+
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2704
|
+
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
2705
|
+
]
|
|
2706
|
+
}
|
|
2707
|
+
],
|
|
2708
|
+
outputs: [
|
|
2709
|
+
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
2710
|
+
{ name: "error", type: "string", internalType: "string" },
|
|
2711
|
+
{ name: "decryptedValue", type: "uint256", internalType: "uint256" }
|
|
2712
|
+
],
|
|
2713
|
+
stateMutability: "view"
|
|
2714
|
+
},
|
|
2715
|
+
{
|
|
2716
|
+
type: "function",
|
|
2717
|
+
name: "decryptForTxWithoutPermit",
|
|
2718
|
+
inputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
|
|
2719
|
+
outputs: [
|
|
2720
|
+
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
2721
|
+
{ name: "error", type: "string", internalType: "string" },
|
|
2722
|
+
{ name: "decryptedValue", type: "uint256", internalType: "uint256" }
|
|
2723
|
+
],
|
|
2724
|
+
stateMutability: "view"
|
|
2725
|
+
}
|
|
2537
2726
|
];
|
|
2538
2727
|
|
|
2539
|
-
// core/decrypt/
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
await sleep(mocksSealOutputDelay);
|
|
2728
|
+
// core/decrypt/cofheMocksDecryptForView.ts
|
|
2729
|
+
async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient, mocksDecryptDelay) {
|
|
2730
|
+
if (mocksDecryptDelay > 0)
|
|
2731
|
+
await sleep(mocksDecryptDelay);
|
|
2544
2732
|
const permission = PermitUtils.getPermission(permit, true);
|
|
2545
2733
|
const permissionWithBigInts = {
|
|
2546
2734
|
...permission,
|
|
@@ -2548,19 +2736,19 @@ async function cofheMocksSealOutput(ctHash, utype, permit, publicClient, mocksSe
|
|
|
2548
2736
|
validatorId: BigInt(permission.validatorId)
|
|
2549
2737
|
};
|
|
2550
2738
|
const [allowed, error, result] = await publicClient.readContract({
|
|
2551
|
-
address:
|
|
2552
|
-
abi:
|
|
2739
|
+
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
2740
|
+
abi: MockThresholdNetworkAbi,
|
|
2553
2741
|
functionName: "querySealOutput",
|
|
2554
2742
|
args: [ctHash, BigInt(utype), permissionWithBigInts]
|
|
2555
2743
|
});
|
|
2556
2744
|
if (error != "") {
|
|
2557
|
-
throw new
|
|
2745
|
+
throw new CofheError({
|
|
2558
2746
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2559
2747
|
message: `mocks querySealOutput call failed: ${error}`
|
|
2560
2748
|
});
|
|
2561
2749
|
}
|
|
2562
2750
|
if (allowed == false) {
|
|
2563
|
-
throw new
|
|
2751
|
+
throw new CofheError({
|
|
2564
2752
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2565
2753
|
message: `mocks querySealOutput call failed: ACL Access Denied (NotAllowed)`
|
|
2566
2754
|
});
|
|
@@ -2579,7 +2767,7 @@ function numberArrayToUint8Array(arr) {
|
|
|
2579
2767
|
}
|
|
2580
2768
|
function convertSealedData(sealed) {
|
|
2581
2769
|
if (!sealed) {
|
|
2582
|
-
throw new
|
|
2770
|
+
throw new CofheError({
|
|
2583
2771
|
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2584
2772
|
message: "Sealed data is missing from completed response"
|
|
2585
2773
|
});
|
|
@@ -2606,7 +2794,7 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
2606
2794
|
body: JSON.stringify(body)
|
|
2607
2795
|
});
|
|
2608
2796
|
} catch (e) {
|
|
2609
|
-
throw new
|
|
2797
|
+
throw new CofheError({
|
|
2610
2798
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2611
2799
|
message: `sealOutput request failed`,
|
|
2612
2800
|
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
@@ -2625,7 +2813,7 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
2625
2813
|
} catch {
|
|
2626
2814
|
errorMessage = response.statusText || errorMessage;
|
|
2627
2815
|
}
|
|
2628
|
-
throw new
|
|
2816
|
+
throw new CofheError({
|
|
2629
2817
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2630
2818
|
message: `sealOutput request failed: ${errorMessage}`,
|
|
2631
2819
|
hint: "Check the threshold network URL and request parameters.",
|
|
@@ -2641,7 +2829,7 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
2641
2829
|
try {
|
|
2642
2830
|
submitResponse = await response.json();
|
|
2643
2831
|
} catch (e) {
|
|
2644
|
-
throw new
|
|
2832
|
+
throw new CofheError({
|
|
2645
2833
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2646
2834
|
message: `Failed to parse sealOutput submit response`,
|
|
2647
2835
|
cause: e instanceof Error ? e : void 0,
|
|
@@ -2652,7 +2840,7 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
2652
2840
|
});
|
|
2653
2841
|
}
|
|
2654
2842
|
if (!submitResponse.request_id) {
|
|
2655
|
-
throw new
|
|
2843
|
+
throw new CofheError({
|
|
2656
2844
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2657
2845
|
message: `sealOutput submit response missing request_id`,
|
|
2658
2846
|
context: {
|
|
@@ -2669,7 +2857,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2669
2857
|
let completed = false;
|
|
2670
2858
|
while (!completed) {
|
|
2671
2859
|
if (Date.now() - startTime > POLL_TIMEOUT_MS) {
|
|
2672
|
-
throw new
|
|
2860
|
+
throw new CofheError({
|
|
2673
2861
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2674
2862
|
message: `sealOutput polling timed out after ${POLL_TIMEOUT_MS}ms`,
|
|
2675
2863
|
hint: "The request may still be processing. Try again later.",
|
|
@@ -2689,7 +2877,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2689
2877
|
}
|
|
2690
2878
|
});
|
|
2691
2879
|
} catch (e) {
|
|
2692
|
-
throw new
|
|
2880
|
+
throw new CofheError({
|
|
2693
2881
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2694
2882
|
message: `sealOutput status poll failed`,
|
|
2695
2883
|
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
@@ -2701,7 +2889,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2701
2889
|
});
|
|
2702
2890
|
}
|
|
2703
2891
|
if (response.status === 404) {
|
|
2704
|
-
throw new
|
|
2892
|
+
throw new CofheError({
|
|
2705
2893
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2706
2894
|
message: `sealOutput request not found: ${requestId}`,
|
|
2707
2895
|
hint: "The request may have expired or been invalid.",
|
|
@@ -2719,7 +2907,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2719
2907
|
} catch {
|
|
2720
2908
|
errorMessage = response.statusText || errorMessage;
|
|
2721
2909
|
}
|
|
2722
|
-
throw new
|
|
2910
|
+
throw new CofheError({
|
|
2723
2911
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2724
2912
|
message: `sealOutput status poll failed: ${errorMessage}`,
|
|
2725
2913
|
context: {
|
|
@@ -2734,7 +2922,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2734
2922
|
try {
|
|
2735
2923
|
statusResponse = await response.json();
|
|
2736
2924
|
} catch (e) {
|
|
2737
|
-
throw new
|
|
2925
|
+
throw new CofheError({
|
|
2738
2926
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2739
2927
|
message: `Failed to parse sealOutput status response`,
|
|
2740
2928
|
cause: e instanceof Error ? e : void 0,
|
|
@@ -2747,7 +2935,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2747
2935
|
if (statusResponse.status === "COMPLETED") {
|
|
2748
2936
|
if (statusResponse.is_succeed === false) {
|
|
2749
2937
|
const errorMessage = statusResponse.error_message || "Unknown error";
|
|
2750
|
-
throw new
|
|
2938
|
+
throw new CofheError({
|
|
2751
2939
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2752
2940
|
message: `sealOutput request failed: ${errorMessage}`,
|
|
2753
2941
|
context: {
|
|
@@ -2758,7 +2946,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2758
2946
|
});
|
|
2759
2947
|
}
|
|
2760
2948
|
if (!statusResponse.sealed) {
|
|
2761
|
-
throw new
|
|
2949
|
+
throw new CofheError({
|
|
2762
2950
|
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2763
2951
|
message: `sealOutput request completed but returned no sealed data`,
|
|
2764
2952
|
context: {
|
|
@@ -2772,7 +2960,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2772
2960
|
}
|
|
2773
2961
|
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
2774
2962
|
}
|
|
2775
|
-
throw new
|
|
2963
|
+
throw new CofheError({
|
|
2776
2964
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2777
2965
|
message: "Polling loop exited unexpectedly",
|
|
2778
2966
|
context: {
|
|
@@ -2785,9 +2973,99 @@ async function tnSealOutputV2(ctHash, chainId, permission, thresholdNetworkUrl)
|
|
|
2785
2973
|
const requestId = await submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission);
|
|
2786
2974
|
return await pollSealOutputStatus(thresholdNetworkUrl, requestId);
|
|
2787
2975
|
}
|
|
2976
|
+
async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient, mocksDecryptForTxDelay) {
|
|
2977
|
+
if (mocksDecryptForTxDelay > 0)
|
|
2978
|
+
await sleep(mocksDecryptForTxDelay);
|
|
2979
|
+
if (permit !== null) {
|
|
2980
|
+
let permission = PermitUtils.getPermission(permit, true);
|
|
2981
|
+
const permissionWithBigInts = {
|
|
2982
|
+
...permission,
|
|
2983
|
+
expiration: BigInt(permission.expiration),
|
|
2984
|
+
validatorId: BigInt(permission.validatorId)
|
|
2985
|
+
};
|
|
2986
|
+
const [allowed2, error2, result2] = await publicClient.readContract({
|
|
2987
|
+
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
2988
|
+
abi: MockThresholdNetworkAbi,
|
|
2989
|
+
functionName: "decryptForTxWithPermit",
|
|
2990
|
+
args: [ctHash, permissionWithBigInts]
|
|
2991
|
+
});
|
|
2992
|
+
if (error2 != "") {
|
|
2993
|
+
throw new CofheError({
|
|
2994
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
2995
|
+
message: `mocks decryptForTx call failed: ${error2}`
|
|
2996
|
+
});
|
|
2997
|
+
}
|
|
2998
|
+
if (allowed2 == false) {
|
|
2999
|
+
throw new CofheError({
|
|
3000
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3001
|
+
message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
|
|
3002
|
+
});
|
|
3003
|
+
}
|
|
3004
|
+
const chainId2 = await publicClient.getChainId();
|
|
3005
|
+
const ctHashBigInt2 = BigInt(ctHash);
|
|
3006
|
+
const resultBigInt2 = BigInt(result2);
|
|
3007
|
+
const encryptionType2 = Number((ctHashBigInt2 & 0x7fn << 8n) >> 8n);
|
|
3008
|
+
const ctHashBytes322 = viem.pad(viem.toHex(ctHashBigInt2), { size: 32 });
|
|
3009
|
+
const packed2 = viem.encodePacked(
|
|
3010
|
+
["uint256", "uint32", "uint64", "bytes32"],
|
|
3011
|
+
[resultBigInt2, encryptionType2, BigInt(chainId2), ctHashBytes322]
|
|
3012
|
+
);
|
|
3013
|
+
const messageHash2 = viem.keccak256(packed2);
|
|
3014
|
+
const signatureHex2 = await accounts.sign({
|
|
3015
|
+
hash: messageHash2,
|
|
3016
|
+
privateKey: MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY,
|
|
3017
|
+
to: "hex"
|
|
3018
|
+
});
|
|
3019
|
+
const signature2 = signatureHex2.slice(2);
|
|
3020
|
+
return {
|
|
3021
|
+
ctHash,
|
|
3022
|
+
decryptedValue: BigInt(result2),
|
|
3023
|
+
signature: signature2
|
|
3024
|
+
};
|
|
3025
|
+
}
|
|
3026
|
+
const [allowed, error, result] = await publicClient.readContract({
|
|
3027
|
+
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
3028
|
+
abi: MockThresholdNetworkAbi,
|
|
3029
|
+
functionName: "decryptForTxWithoutPermit",
|
|
3030
|
+
args: [ctHash]
|
|
3031
|
+
});
|
|
3032
|
+
if (error != "") {
|
|
3033
|
+
throw new CofheError({
|
|
3034
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3035
|
+
message: `mocks decryptForTx call failed: ${error}`
|
|
3036
|
+
});
|
|
3037
|
+
}
|
|
3038
|
+
if (allowed == false) {
|
|
3039
|
+
throw new CofheError({
|
|
3040
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3041
|
+
message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
|
|
3042
|
+
});
|
|
3043
|
+
}
|
|
3044
|
+
const chainId = await publicClient.getChainId();
|
|
3045
|
+
const ctHashBigInt = BigInt(ctHash);
|
|
3046
|
+
const resultBigInt = BigInt(result);
|
|
3047
|
+
const encryptionType = Number((ctHashBigInt & 0x7fn << 8n) >> 8n);
|
|
3048
|
+
const ctHashBytes32 = viem.pad(viem.toHex(ctHashBigInt), { size: 32 });
|
|
3049
|
+
const packed = viem.encodePacked(
|
|
3050
|
+
["uint256", "uint32", "uint64", "bytes32"],
|
|
3051
|
+
[resultBigInt, encryptionType, BigInt(chainId), ctHashBytes32]
|
|
3052
|
+
);
|
|
3053
|
+
const messageHash = viem.keccak256(packed);
|
|
3054
|
+
const signatureHex = await accounts.sign({
|
|
3055
|
+
hash: messageHash,
|
|
3056
|
+
privateKey: MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY,
|
|
3057
|
+
to: "hex"
|
|
3058
|
+
});
|
|
3059
|
+
const signature = signatureHex.slice(2);
|
|
3060
|
+
return {
|
|
3061
|
+
ctHash,
|
|
3062
|
+
decryptedValue: BigInt(result),
|
|
3063
|
+
signature
|
|
3064
|
+
};
|
|
3065
|
+
}
|
|
2788
3066
|
|
|
2789
|
-
// core/decrypt/
|
|
2790
|
-
var
|
|
3067
|
+
// core/decrypt/decryptForViewBuilder.ts
|
|
3068
|
+
var DecryptForViewBuilder = class extends BaseBuilder {
|
|
2791
3069
|
ctHash;
|
|
2792
3070
|
utype;
|
|
2793
3071
|
permitHash;
|
|
@@ -2813,12 +3091,12 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2813
3091
|
*
|
|
2814
3092
|
* Example:
|
|
2815
3093
|
* ```typescript
|
|
2816
|
-
* const unsealed = await
|
|
3094
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2817
3095
|
* .setChainId(11155111)
|
|
2818
|
-
* .
|
|
3096
|
+
* .execute();
|
|
2819
3097
|
* ```
|
|
2820
3098
|
*
|
|
2821
|
-
* @returns The chainable
|
|
3099
|
+
* @returns The chainable DecryptForViewBuilder instance.
|
|
2822
3100
|
*/
|
|
2823
3101
|
setChainId(chainId) {
|
|
2824
3102
|
this.chainId = chainId;
|
|
@@ -2834,12 +3112,12 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2834
3112
|
*
|
|
2835
3113
|
* Example:
|
|
2836
3114
|
* ```typescript
|
|
2837
|
-
* const unsealed = await
|
|
3115
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2838
3116
|
* .setAccount('0x1234567890123456789012345678901234567890')
|
|
2839
|
-
* .
|
|
3117
|
+
* .execute();
|
|
2840
3118
|
* ```
|
|
2841
3119
|
*
|
|
2842
|
-
* @returns The chainable
|
|
3120
|
+
* @returns The chainable DecryptForViewBuilder instance.
|
|
2843
3121
|
*/
|
|
2844
3122
|
setAccount(account) {
|
|
2845
3123
|
this.account = account;
|
|
@@ -2848,6 +3126,19 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2848
3126
|
getAccount() {
|
|
2849
3127
|
return this.account;
|
|
2850
3128
|
}
|
|
3129
|
+
withPermit(permitOrPermitHash) {
|
|
3130
|
+
if (typeof permitOrPermitHash === "string") {
|
|
3131
|
+
this.permitHash = permitOrPermitHash;
|
|
3132
|
+
this.permit = void 0;
|
|
3133
|
+
} else if (permitOrPermitHash === void 0) {
|
|
3134
|
+
this.permitHash = void 0;
|
|
3135
|
+
this.permit = void 0;
|
|
3136
|
+
} else {
|
|
3137
|
+
this.permit = permitOrPermitHash;
|
|
3138
|
+
this.permitHash = void 0;
|
|
3139
|
+
}
|
|
3140
|
+
return this;
|
|
3141
|
+
}
|
|
2851
3142
|
/**
|
|
2852
3143
|
* @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
|
|
2853
3144
|
*
|
|
@@ -2856,16 +3147,16 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2856
3147
|
*
|
|
2857
3148
|
* Example:
|
|
2858
3149
|
* ```typescript
|
|
2859
|
-
* const unsealed = await
|
|
3150
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2860
3151
|
* .setPermitHash('0x1234567890123456789012345678901234567890')
|
|
2861
|
-
* .
|
|
3152
|
+
* .execute();
|
|
2862
3153
|
* ```
|
|
2863
3154
|
*
|
|
2864
|
-
* @returns The chainable
|
|
3155
|
+
* @returns The chainable DecryptForViewBuilder instance.
|
|
2865
3156
|
*/
|
|
3157
|
+
/** @deprecated Use `withPermit(permitHash)` instead. */
|
|
2866
3158
|
setPermitHash(permitHash) {
|
|
2867
|
-
this.permitHash
|
|
2868
|
-
return this;
|
|
3159
|
+
return this.withPermit(permitHash);
|
|
2869
3160
|
}
|
|
2870
3161
|
getPermitHash() {
|
|
2871
3162
|
return this.permitHash;
|
|
@@ -2877,16 +3168,16 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2877
3168
|
*
|
|
2878
3169
|
* Example:
|
|
2879
3170
|
* ```typescript
|
|
2880
|
-
* const unsealed = await
|
|
3171
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2881
3172
|
* .setPermit(permit)
|
|
2882
|
-
* .
|
|
3173
|
+
* .execute();
|
|
2883
3174
|
* ```
|
|
2884
3175
|
*
|
|
2885
|
-
* @returns The chainable
|
|
3176
|
+
* @returns The chainable DecryptForViewBuilder instance.
|
|
2886
3177
|
*/
|
|
3178
|
+
/** @deprecated Use `withPermit(permit)` instead. */
|
|
2887
3179
|
setPermit(permit) {
|
|
2888
|
-
this.permit
|
|
2889
|
-
return this;
|
|
3180
|
+
return this.withPermit(permit);
|
|
2890
3181
|
}
|
|
2891
3182
|
getPermit() {
|
|
2892
3183
|
return this.permit;
|
|
@@ -2897,7 +3188,7 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2897
3188
|
}
|
|
2898
3189
|
validateUtypeOrThrow() {
|
|
2899
3190
|
if (!isValidUtype(this.utype))
|
|
2900
|
-
throw new
|
|
3191
|
+
throw new CofheError({
|
|
2901
3192
|
code: "INVALID_UTYPE" /* InvalidUtype */,
|
|
2902
3193
|
message: `Invalid utype to decrypt to`,
|
|
2903
3194
|
context: {
|
|
@@ -2913,7 +3204,7 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2913
3204
|
if (this.permitHash) {
|
|
2914
3205
|
const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
|
|
2915
3206
|
if (!permit2) {
|
|
2916
|
-
throw new
|
|
3207
|
+
throw new CofheError({
|
|
2917
3208
|
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
2918
3209
|
message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
|
|
2919
3210
|
hint: "Ensure the permit exists and is valid.",
|
|
@@ -2928,7 +3219,7 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2928
3219
|
}
|
|
2929
3220
|
const permit = await permits.getActivePermit(this.chainId, this.account);
|
|
2930
3221
|
if (!permit) {
|
|
2931
|
-
throw new
|
|
3222
|
+
throw new CofheError({
|
|
2932
3223
|
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
2933
3224
|
message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
|
|
2934
3225
|
hint: "Ensure a permit exists for this account on this chain.",
|
|
@@ -2945,8 +3236,8 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2945
3236
|
*/
|
|
2946
3237
|
async mocksSealOutput(permit) {
|
|
2947
3238
|
this.assertPublicClient();
|
|
2948
|
-
const
|
|
2949
|
-
return
|
|
3239
|
+
const mocksDecryptDelay = this.config.mocks.decryptDelay;
|
|
3240
|
+
return cofheMocksDecryptForView(this.ctHash, this.utype, permit, this.publicClient, mocksDecryptDelay);
|
|
2950
3241
|
}
|
|
2951
3242
|
/**
|
|
2952
3243
|
* In the production context, perform a true decryption with the CoFHE coprocessor.
|
|
@@ -2971,15 +3262,16 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2971
3262
|
*
|
|
2972
3263
|
* Example:
|
|
2973
3264
|
* ```typescript
|
|
2974
|
-
* const unsealed = await
|
|
3265
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2975
3266
|
* .setChainId(11155111) // optional
|
|
2976
3267
|
* .setAccount('0x123...890') // optional
|
|
2977
|
-
* .
|
|
3268
|
+
* .withPermit() // optional
|
|
3269
|
+
* .execute(); // execute
|
|
2978
3270
|
* ```
|
|
2979
3271
|
*
|
|
2980
3272
|
* @returns The unsealed item.
|
|
2981
3273
|
*/
|
|
2982
|
-
async
|
|
3274
|
+
async execute() {
|
|
2983
3275
|
this.validateUtypeOrThrow();
|
|
2984
3276
|
const permit = await this.getResolvedPermit();
|
|
2985
3277
|
PermitUtils.validate(permit);
|
|
@@ -2995,6 +3287,394 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2995
3287
|
}
|
|
2996
3288
|
};
|
|
2997
3289
|
|
|
3290
|
+
// core/decrypt/tnDecrypt.ts
|
|
3291
|
+
function normalizeSignature(signature) {
|
|
3292
|
+
if (typeof signature !== "string") {
|
|
3293
|
+
throw new CofheError({
|
|
3294
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3295
|
+
message: "decrypt response missing signature",
|
|
3296
|
+
context: {
|
|
3297
|
+
signature
|
|
3298
|
+
}
|
|
3299
|
+
});
|
|
3300
|
+
}
|
|
3301
|
+
const trimmed = signature.trim();
|
|
3302
|
+
if (trimmed.length === 0) {
|
|
3303
|
+
throw new CofheError({
|
|
3304
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3305
|
+
message: "decrypt response returned empty signature"
|
|
3306
|
+
});
|
|
3307
|
+
}
|
|
3308
|
+
return trimmed.startsWith("0x") ? trimmed.slice(2) : trimmed;
|
|
3309
|
+
}
|
|
3310
|
+
function parseDecryptedBytesToBigInt(decrypted) {
|
|
3311
|
+
if (!Array.isArray(decrypted)) {
|
|
3312
|
+
throw new CofheError({
|
|
3313
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3314
|
+
message: "decrypt response field <decrypted> must be a byte array",
|
|
3315
|
+
context: {
|
|
3316
|
+
decrypted
|
|
3317
|
+
}
|
|
3318
|
+
});
|
|
3319
|
+
}
|
|
3320
|
+
if (decrypted.length === 0) {
|
|
3321
|
+
throw new CofheError({
|
|
3322
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3323
|
+
message: "decrypt response field <decrypted> was an empty byte array",
|
|
3324
|
+
context: {
|
|
3325
|
+
decrypted
|
|
3326
|
+
}
|
|
3327
|
+
});
|
|
3328
|
+
}
|
|
3329
|
+
let hex = "";
|
|
3330
|
+
for (const b of decrypted) {
|
|
3331
|
+
if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
|
|
3332
|
+
throw new CofheError({
|
|
3333
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3334
|
+
message: "decrypt response field <decrypted> contained a non-byte value",
|
|
3335
|
+
context: {
|
|
3336
|
+
badElement: b,
|
|
3337
|
+
decrypted
|
|
3338
|
+
}
|
|
3339
|
+
});
|
|
3340
|
+
}
|
|
3341
|
+
hex += b.toString(16).padStart(2, "0");
|
|
3342
|
+
}
|
|
3343
|
+
return BigInt(`0x${hex}`);
|
|
3344
|
+
}
|
|
3345
|
+
function assertTnDecryptResponse(value) {
|
|
3346
|
+
if (value == null || typeof value !== "object") {
|
|
3347
|
+
throw new CofheError({
|
|
3348
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3349
|
+
message: "decrypt response must be a JSON object",
|
|
3350
|
+
context: {
|
|
3351
|
+
value
|
|
3352
|
+
}
|
|
3353
|
+
});
|
|
3354
|
+
}
|
|
3355
|
+
const v = value;
|
|
3356
|
+
const decrypted = v.decrypted;
|
|
3357
|
+
const signature = v.signature;
|
|
3358
|
+
const encryptionType = v.encryption_type;
|
|
3359
|
+
const errorMessage = v.error_message;
|
|
3360
|
+
if (!Array.isArray(decrypted)) {
|
|
3361
|
+
throw new CofheError({
|
|
3362
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3363
|
+
message: "decrypt response missing <decrypted> byte array",
|
|
3364
|
+
context: { decryptResponse: value }
|
|
3365
|
+
});
|
|
3366
|
+
}
|
|
3367
|
+
if (typeof signature !== "string") {
|
|
3368
|
+
throw new CofheError({
|
|
3369
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3370
|
+
message: "decrypt response missing <signature> string",
|
|
3371
|
+
context: { decryptResponse: value }
|
|
3372
|
+
});
|
|
3373
|
+
}
|
|
3374
|
+
if (typeof encryptionType !== "number") {
|
|
3375
|
+
throw new CofheError({
|
|
3376
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3377
|
+
message: "decrypt response missing <encryption_type> number",
|
|
3378
|
+
context: { decryptResponse: value }
|
|
3379
|
+
});
|
|
3380
|
+
}
|
|
3381
|
+
if (!(typeof errorMessage === "string" || errorMessage === null)) {
|
|
3382
|
+
throw new CofheError({
|
|
3383
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3384
|
+
message: "decrypt response field <error_message> must be string or null",
|
|
3385
|
+
context: { decryptResponse: value }
|
|
3386
|
+
});
|
|
3387
|
+
}
|
|
3388
|
+
return {
|
|
3389
|
+
decrypted,
|
|
3390
|
+
signature,
|
|
3391
|
+
encryption_type: encryptionType,
|
|
3392
|
+
error_message: errorMessage
|
|
3393
|
+
};
|
|
3394
|
+
}
|
|
3395
|
+
async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
|
|
3396
|
+
const body = {
|
|
3397
|
+
ct_tempkey: ctHash.toString(16).padStart(64, "0"),
|
|
3398
|
+
host_chain_id: chainId
|
|
3399
|
+
};
|
|
3400
|
+
if (permission) {
|
|
3401
|
+
body.permit = permission;
|
|
3402
|
+
}
|
|
3403
|
+
let response;
|
|
3404
|
+
try {
|
|
3405
|
+
response = await fetch(`${thresholdNetworkUrl}/decrypt`, {
|
|
3406
|
+
method: "POST",
|
|
3407
|
+
headers: {
|
|
3408
|
+
"Content-Type": "application/json"
|
|
3409
|
+
},
|
|
3410
|
+
body: JSON.stringify(body)
|
|
3411
|
+
});
|
|
3412
|
+
} catch (e) {
|
|
3413
|
+
throw new CofheError({
|
|
3414
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3415
|
+
message: `decrypt request failed`,
|
|
3416
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3417
|
+
cause: e instanceof Error ? e : void 0,
|
|
3418
|
+
context: {
|
|
3419
|
+
thresholdNetworkUrl,
|
|
3420
|
+
body
|
|
3421
|
+
}
|
|
3422
|
+
});
|
|
3423
|
+
}
|
|
3424
|
+
const responseText = await response.text();
|
|
3425
|
+
if (!response.ok) {
|
|
3426
|
+
let errorMessage = response.statusText || `HTTP ${response.status}`;
|
|
3427
|
+
try {
|
|
3428
|
+
const errorBody = JSON.parse(responseText);
|
|
3429
|
+
const maybeMessage = errorBody.error_message || errorBody.message;
|
|
3430
|
+
if (typeof maybeMessage === "string" && maybeMessage.length > 0)
|
|
3431
|
+
errorMessage = maybeMessage;
|
|
3432
|
+
} catch {
|
|
3433
|
+
const trimmed = responseText.trim();
|
|
3434
|
+
if (trimmed.length > 0)
|
|
3435
|
+
errorMessage = trimmed;
|
|
3436
|
+
}
|
|
3437
|
+
throw new CofheError({
|
|
3438
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3439
|
+
message: `decrypt request failed: ${errorMessage}`,
|
|
3440
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
3441
|
+
context: {
|
|
3442
|
+
thresholdNetworkUrl,
|
|
3443
|
+
status: response.status,
|
|
3444
|
+
statusText: response.statusText,
|
|
3445
|
+
body,
|
|
3446
|
+
responseText
|
|
3447
|
+
}
|
|
3448
|
+
});
|
|
3449
|
+
}
|
|
3450
|
+
let rawJson;
|
|
3451
|
+
try {
|
|
3452
|
+
rawJson = JSON.parse(responseText);
|
|
3453
|
+
} catch (e) {
|
|
3454
|
+
throw new CofheError({
|
|
3455
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3456
|
+
message: `Failed to parse decrypt response`,
|
|
3457
|
+
cause: e instanceof Error ? e : void 0,
|
|
3458
|
+
context: {
|
|
3459
|
+
thresholdNetworkUrl,
|
|
3460
|
+
body,
|
|
3461
|
+
responseText
|
|
3462
|
+
}
|
|
3463
|
+
});
|
|
3464
|
+
}
|
|
3465
|
+
const decryptResponse = assertTnDecryptResponse(rawJson);
|
|
3466
|
+
if (decryptResponse.error_message) {
|
|
3467
|
+
throw new CofheError({
|
|
3468
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3469
|
+
message: `decrypt request failed: ${decryptResponse.error_message}`,
|
|
3470
|
+
context: {
|
|
3471
|
+
thresholdNetworkUrl,
|
|
3472
|
+
body,
|
|
3473
|
+
decryptResponse
|
|
3474
|
+
}
|
|
3475
|
+
});
|
|
3476
|
+
}
|
|
3477
|
+
const decryptedValue = parseDecryptedBytesToBigInt(decryptResponse.decrypted);
|
|
3478
|
+
const signature = normalizeSignature(decryptResponse.signature);
|
|
3479
|
+
return { decryptedValue, signature };
|
|
3480
|
+
}
|
|
3481
|
+
|
|
3482
|
+
// core/decrypt/decryptForTxBuilder.ts
|
|
3483
|
+
var DecryptForTxBuilder = class extends BaseBuilder {
|
|
3484
|
+
ctHash;
|
|
3485
|
+
permitHash;
|
|
3486
|
+
permit;
|
|
3487
|
+
permitSelection = "unset";
|
|
3488
|
+
constructor(params) {
|
|
3489
|
+
super({
|
|
3490
|
+
config: params.config,
|
|
3491
|
+
publicClient: params.publicClient,
|
|
3492
|
+
walletClient: params.walletClient,
|
|
3493
|
+
chainId: params.chainId,
|
|
3494
|
+
account: params.account,
|
|
3495
|
+
requireConnected: params.requireConnected
|
|
3496
|
+
});
|
|
3497
|
+
this.ctHash = params.ctHash;
|
|
3498
|
+
}
|
|
3499
|
+
setChainId(chainId) {
|
|
3500
|
+
this.chainId = chainId;
|
|
3501
|
+
return this;
|
|
3502
|
+
}
|
|
3503
|
+
getChainId() {
|
|
3504
|
+
return this.chainId;
|
|
3505
|
+
}
|
|
3506
|
+
setAccount(account) {
|
|
3507
|
+
this.account = account;
|
|
3508
|
+
return this;
|
|
3509
|
+
}
|
|
3510
|
+
getAccount() {
|
|
3511
|
+
return this.account;
|
|
3512
|
+
}
|
|
3513
|
+
withPermit(permitOrPermitHash) {
|
|
3514
|
+
if (this.permitSelection === "with-permit") {
|
|
3515
|
+
throw new CofheError({
|
|
3516
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3517
|
+
message: "decryptForTx: withPermit() can only be selected once.",
|
|
3518
|
+
hint: "Choose the permit mode once. If you need a different permit, start a new decryptForTx() builder chain."
|
|
3519
|
+
});
|
|
3520
|
+
}
|
|
3521
|
+
if (this.permitSelection === "without-permit") {
|
|
3522
|
+
throw new CofheError({
|
|
3523
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3524
|
+
message: "decryptForTx: cannot call withPermit() after withoutPermit() has been selected.",
|
|
3525
|
+
hint: "Choose exactly one permit mode: either call .withPermit(...) or .withoutPermit(), but not both."
|
|
3526
|
+
});
|
|
3527
|
+
}
|
|
3528
|
+
this.permitSelection = "with-permit";
|
|
3529
|
+
if (typeof permitOrPermitHash === "string") {
|
|
3530
|
+
this.permitHash = permitOrPermitHash;
|
|
3531
|
+
this.permit = void 0;
|
|
3532
|
+
} else if (permitOrPermitHash === void 0) {
|
|
3533
|
+
this.permitHash = void 0;
|
|
3534
|
+
this.permit = void 0;
|
|
3535
|
+
} else {
|
|
3536
|
+
this.permit = permitOrPermitHash;
|
|
3537
|
+
this.permitHash = void 0;
|
|
3538
|
+
}
|
|
3539
|
+
return this;
|
|
3540
|
+
}
|
|
3541
|
+
/**
|
|
3542
|
+
* Select "no permit" mode.
|
|
3543
|
+
*
|
|
3544
|
+
* This uses global allowance (no permit required) and sends an empty permission payload to `/decrypt`.
|
|
3545
|
+
*/
|
|
3546
|
+
withoutPermit() {
|
|
3547
|
+
if (this.permitSelection === "without-permit") {
|
|
3548
|
+
throw new CofheError({
|
|
3549
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3550
|
+
message: "decryptForTx: withoutPermit() can only be selected once.",
|
|
3551
|
+
hint: "Choose the permit mode once. If you need a different mode, start a new decryptForTx() builder chain."
|
|
3552
|
+
});
|
|
3553
|
+
}
|
|
3554
|
+
if (this.permitSelection === "with-permit") {
|
|
3555
|
+
throw new CofheError({
|
|
3556
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3557
|
+
message: "decryptForTx: cannot call withoutPermit() after withPermit() has been selected.",
|
|
3558
|
+
hint: "Choose exactly one permit mode: either call .withPermit(...) or .withoutPermit(), but not both."
|
|
3559
|
+
});
|
|
3560
|
+
}
|
|
3561
|
+
this.permitSelection = "without-permit";
|
|
3562
|
+
this.permitHash = void 0;
|
|
3563
|
+
this.permit = void 0;
|
|
3564
|
+
return this;
|
|
3565
|
+
}
|
|
3566
|
+
getPermit() {
|
|
3567
|
+
return this.permit;
|
|
3568
|
+
}
|
|
3569
|
+
getPermitHash() {
|
|
3570
|
+
return this.permitHash;
|
|
3571
|
+
}
|
|
3572
|
+
async getThresholdNetworkUrl() {
|
|
3573
|
+
this.assertChainId();
|
|
3574
|
+
return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
|
|
3575
|
+
}
|
|
3576
|
+
async getResolvedPermit() {
|
|
3577
|
+
if (this.permitSelection === "unset") {
|
|
3578
|
+
throw new CofheError({
|
|
3579
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3580
|
+
message: "decryptForTx: missing permit selection; call withPermit(...) or withoutPermit() before execute().",
|
|
3581
|
+
hint: "Call .withPermit() to use the active permit, or .withoutPermit() for global allowance."
|
|
3582
|
+
});
|
|
3583
|
+
}
|
|
3584
|
+
if (this.permitSelection === "without-permit") {
|
|
3585
|
+
return null;
|
|
3586
|
+
}
|
|
3587
|
+
if (this.permit)
|
|
3588
|
+
return this.permit;
|
|
3589
|
+
this.assertChainId();
|
|
3590
|
+
this.assertAccount();
|
|
3591
|
+
if (this.permitHash) {
|
|
3592
|
+
const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
|
|
3593
|
+
if (!permit2) {
|
|
3594
|
+
throw new CofheError({
|
|
3595
|
+
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
3596
|
+
message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
|
|
3597
|
+
hint: "Ensure the permit exists and is valid.",
|
|
3598
|
+
context: {
|
|
3599
|
+
chainId: this.chainId,
|
|
3600
|
+
account: this.account,
|
|
3601
|
+
permitHash: this.permitHash
|
|
3602
|
+
}
|
|
3603
|
+
});
|
|
3604
|
+
}
|
|
3605
|
+
return permit2;
|
|
3606
|
+
}
|
|
3607
|
+
const permit = await permits.getActivePermit(this.chainId, this.account);
|
|
3608
|
+
if (!permit) {
|
|
3609
|
+
throw new CofheError({
|
|
3610
|
+
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
3611
|
+
message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
|
|
3612
|
+
hint: "Create a permit (e.g. client.permits.createSelf(...)) and/or set it active (client.permits.selectActivePermit(hash)).",
|
|
3613
|
+
context: {
|
|
3614
|
+
chainId: this.chainId,
|
|
3615
|
+
account: this.account
|
|
3616
|
+
}
|
|
3617
|
+
});
|
|
3618
|
+
}
|
|
3619
|
+
return permit;
|
|
3620
|
+
}
|
|
3621
|
+
/**
|
|
3622
|
+
* On hardhat, interact with MockThresholdNetwork contract
|
|
3623
|
+
*/
|
|
3624
|
+
async mocksDecryptForTx(permit) {
|
|
3625
|
+
this.assertPublicClient();
|
|
3626
|
+
const delay = this.config.mocks.decryptDelay;
|
|
3627
|
+
const result = await cofheMocksDecryptForTx(this.ctHash, 0, permit, this.publicClient, delay);
|
|
3628
|
+
return result;
|
|
3629
|
+
}
|
|
3630
|
+
/**
|
|
3631
|
+
* In the production context, perform a true decryption with the CoFHE coprocessor.
|
|
3632
|
+
*/
|
|
3633
|
+
async productionDecryptForTx(permit) {
|
|
3634
|
+
this.assertChainId();
|
|
3635
|
+
this.assertPublicClient();
|
|
3636
|
+
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3637
|
+
const permission = permit ? PermitUtils.getPermission(permit, true) : null;
|
|
3638
|
+
const { decryptedValue, signature } = await tnDecrypt(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
|
|
3639
|
+
return {
|
|
3640
|
+
ctHash: this.ctHash,
|
|
3641
|
+
decryptedValue,
|
|
3642
|
+
signature
|
|
3643
|
+
};
|
|
3644
|
+
}
|
|
3645
|
+
/**
|
|
3646
|
+
* Final step of the decryptForTx process. MUST BE CALLED LAST IN THE CHAIN.
|
|
3647
|
+
*
|
|
3648
|
+
* You must explicitly choose one permit mode before calling `execute()`:
|
|
3649
|
+
* - `withPermit(permit)` / `withPermit(permitHash)` / `withPermit()` (active permit)
|
|
3650
|
+
* - `withoutPermit()` (global allowance)
|
|
3651
|
+
*/
|
|
3652
|
+
async execute() {
|
|
3653
|
+
const permit = await this.getResolvedPermit();
|
|
3654
|
+
if (permit !== null) {
|
|
3655
|
+
PermitUtils.validate(permit);
|
|
3656
|
+
PermitUtils.isValid(permit);
|
|
3657
|
+
const chainId = permit._signedDomain.chainId;
|
|
3658
|
+
if (chainId === hardhat2.id) {
|
|
3659
|
+
return await this.mocksDecryptForTx(permit);
|
|
3660
|
+
} else {
|
|
3661
|
+
return await this.productionDecryptForTx(permit);
|
|
3662
|
+
}
|
|
3663
|
+
} else {
|
|
3664
|
+
if (!this.chainId) {
|
|
3665
|
+
this.assertPublicClient();
|
|
3666
|
+
this.chainId = await getPublicClientChainID(this.publicClient);
|
|
3667
|
+
}
|
|
3668
|
+
this.assertChainId();
|
|
3669
|
+
if (this.chainId === hardhat2.id) {
|
|
3670
|
+
return await this.mocksDecryptForTx(null);
|
|
3671
|
+
} else {
|
|
3672
|
+
return await this.productionDecryptForTx(null);
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
};
|
|
3677
|
+
|
|
2998
3678
|
// core/client.ts
|
|
2999
3679
|
var InitialConnectStore = {
|
|
3000
3680
|
connected: false,
|
|
@@ -3005,9 +3685,10 @@ var InitialConnectStore = {
|
|
|
3005
3685
|
publicClient: void 0,
|
|
3006
3686
|
walletClient: void 0
|
|
3007
3687
|
};
|
|
3008
|
-
function
|
|
3688
|
+
function createCofheClientBase(opts) {
|
|
3009
3689
|
const keysStorage = createKeysStore(opts.config.fheKeyStorage);
|
|
3010
3690
|
const connectStore = vanilla.createStore(() => InitialConnectStore);
|
|
3691
|
+
let connectAttemptId = 0;
|
|
3011
3692
|
const updateConnectState = (partial) => {
|
|
3012
3693
|
connectStore.setState((state) => ({ ...state, ...partial }));
|
|
3013
3694
|
};
|
|
@@ -3015,7 +3696,7 @@ function createCofhesdkClientBase(opts) {
|
|
|
3015
3696
|
const state = connectStore.getState();
|
|
3016
3697
|
const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
|
|
3017
3698
|
if (notConnected) {
|
|
3018
|
-
throw new
|
|
3699
|
+
throw new CofheError({
|
|
3019
3700
|
code: "NOT_CONNECTED" /* NotConnected */,
|
|
3020
3701
|
message: "Client must be connected, account and chainId must be initialized",
|
|
3021
3702
|
hint: "Ensure client.connect() has been called and awaited.",
|
|
@@ -3033,6 +3714,8 @@ function createCofhesdkClientBase(opts) {
|
|
|
3033
3714
|
const state = connectStore.getState();
|
|
3034
3715
|
if (state.connected && state.publicClient === publicClient && state.walletClient === walletClient)
|
|
3035
3716
|
return;
|
|
3717
|
+
connectAttemptId += 1;
|
|
3718
|
+
const localAttemptId = connectAttemptId;
|
|
3036
3719
|
updateConnectState({
|
|
3037
3720
|
...InitialConnectStore,
|
|
3038
3721
|
connecting: true
|
|
@@ -3040,6 +3723,8 @@ function createCofhesdkClientBase(opts) {
|
|
|
3040
3723
|
try {
|
|
3041
3724
|
const chainId = await getPublicClientChainID(publicClient);
|
|
3042
3725
|
const account = await getWalletClientAccount(walletClient);
|
|
3726
|
+
if (localAttemptId !== connectAttemptId)
|
|
3727
|
+
return;
|
|
3043
3728
|
updateConnectState({
|
|
3044
3729
|
connected: true,
|
|
3045
3730
|
connecting: false,
|
|
@@ -3050,6 +3735,8 @@ function createCofhesdkClientBase(opts) {
|
|
|
3050
3735
|
walletClient
|
|
3051
3736
|
});
|
|
3052
3737
|
} catch (e) {
|
|
3738
|
+
if (localAttemptId !== connectAttemptId)
|
|
3739
|
+
return;
|
|
3053
3740
|
updateConnectState({
|
|
3054
3741
|
...InitialConnectStore,
|
|
3055
3742
|
connectError: e
|
|
@@ -3057,6 +3744,10 @@ function createCofhesdkClientBase(opts) {
|
|
|
3057
3744
|
throw e;
|
|
3058
3745
|
}
|
|
3059
3746
|
}
|
|
3747
|
+
function disconnect() {
|
|
3748
|
+
connectAttemptId += 1;
|
|
3749
|
+
updateConnectState({ ...InitialConnectStore });
|
|
3750
|
+
}
|
|
3060
3751
|
function encryptInputs(inputs) {
|
|
3061
3752
|
const state = connectStore.getState();
|
|
3062
3753
|
return new EncryptInputsBuilder({
|
|
@@ -3076,16 +3767,28 @@ function createCofhesdkClientBase(opts) {
|
|
|
3076
3767
|
requireConnected: _requireConnected
|
|
3077
3768
|
});
|
|
3078
3769
|
}
|
|
3079
|
-
function
|
|
3770
|
+
function decryptForView(ctHash, utype) {
|
|
3080
3771
|
const state = connectStore.getState();
|
|
3081
|
-
return new
|
|
3772
|
+
return new DecryptForViewBuilder({
|
|
3082
3773
|
ctHash,
|
|
3083
3774
|
utype,
|
|
3084
|
-
chainId: state.chainId
|
|
3085
|
-
account: state.account
|
|
3775
|
+
chainId: state.chainId,
|
|
3776
|
+
account: state.account,
|
|
3086
3777
|
config: opts.config,
|
|
3087
|
-
publicClient: state.publicClient
|
|
3088
|
-
walletClient: state.walletClient
|
|
3778
|
+
publicClient: state.publicClient,
|
|
3779
|
+
walletClient: state.walletClient,
|
|
3780
|
+
requireConnected: _requireConnected
|
|
3781
|
+
});
|
|
3782
|
+
}
|
|
3783
|
+
function decryptForTx(ctHash) {
|
|
3784
|
+
const state = connectStore.getState();
|
|
3785
|
+
return new DecryptForTxBuilder({
|
|
3786
|
+
ctHash,
|
|
3787
|
+
chainId: state.chainId,
|
|
3788
|
+
account: state.account,
|
|
3789
|
+
config: opts.config,
|
|
3790
|
+
publicClient: state.publicClient,
|
|
3791
|
+
walletClient: state.walletClient,
|
|
3089
3792
|
requireConnected: _requireConnected
|
|
3090
3793
|
});
|
|
3091
3794
|
}
|
|
@@ -3094,7 +3797,7 @@ function createCofhesdkClientBase(opts) {
|
|
|
3094
3797
|
const _chainId = chainId ?? state.chainId;
|
|
3095
3798
|
const _account = account ?? state.account;
|
|
3096
3799
|
if (_chainId == null || _account == null) {
|
|
3097
|
-
throw new
|
|
3800
|
+
throw new CofheError({
|
|
3098
3801
|
code: "NOT_CONNECTED" /* NotConnected */,
|
|
3099
3802
|
message: "ChainId or account not available.",
|
|
3100
3803
|
hint: "Ensure client.connect() has been called, or provide chainId and account explicitly.",
|
|
@@ -3161,9 +3864,9 @@ function createCofhesdkClientBase(opts) {
|
|
|
3161
3864
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
3162
3865
|
return permits.selectActivePermit(_chainId, _account, hash);
|
|
3163
3866
|
},
|
|
3164
|
-
removePermit: async (hash, chainId, account
|
|
3867
|
+
removePermit: async (hash, chainId, account) => {
|
|
3165
3868
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
3166
|
-
return permits.removePermit(_chainId, _account, hash
|
|
3869
|
+
return permits.removePermit(_chainId, _account, hash);
|
|
3167
3870
|
},
|
|
3168
3871
|
removeActivePermit: async (chainId, account) => {
|
|
3169
3872
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
@@ -3179,6 +3882,9 @@ function createCofhesdkClientBase(opts) {
|
|
|
3179
3882
|
getSnapshot: connectStore.getState,
|
|
3180
3883
|
subscribe: connectStore.subscribe,
|
|
3181
3884
|
// flags (read-only: reflect snapshot)
|
|
3885
|
+
get connection() {
|
|
3886
|
+
return connectStore.getState();
|
|
3887
|
+
},
|
|
3182
3888
|
get connected() {
|
|
3183
3889
|
return connectStore.getState().connected;
|
|
3184
3890
|
},
|
|
@@ -3188,8 +3894,14 @@ function createCofhesdkClientBase(opts) {
|
|
|
3188
3894
|
// config & platform-specific (read-only)
|
|
3189
3895
|
config: opts.config,
|
|
3190
3896
|
connect,
|
|
3897
|
+
disconnect,
|
|
3191
3898
|
encryptInputs,
|
|
3192
|
-
|
|
3899
|
+
decryptForView,
|
|
3900
|
+
/**
|
|
3901
|
+
* @deprecated Use `decryptForView` instead. Kept for backward compatibility.
|
|
3902
|
+
*/
|
|
3903
|
+
decryptHandle: decryptForView,
|
|
3904
|
+
decryptForTx,
|
|
3193
3905
|
permits: clientPermits
|
|
3194
3906
|
// Add SDK-specific methods below that require connection
|
|
3195
3907
|
// Example:
|
|
@@ -3265,15 +3977,15 @@ var zkBuilderAndCrsGenerator = (fhe, crs) => {
|
|
|
3265
3977
|
const zkCrs = nodeTfhe.CompactPkeCrs.deserialize(fromHexString2(crs));
|
|
3266
3978
|
return { zkBuilder, zkCrs };
|
|
3267
3979
|
};
|
|
3268
|
-
function
|
|
3269
|
-
return
|
|
3980
|
+
function createCofheConfig(config) {
|
|
3981
|
+
return createCofheConfigBase({
|
|
3270
3982
|
environment: "node",
|
|
3271
3983
|
...config,
|
|
3272
3984
|
fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? createNodeStorage()
|
|
3273
3985
|
});
|
|
3274
3986
|
}
|
|
3275
|
-
function
|
|
3276
|
-
return
|
|
3987
|
+
function createCofheClient(config) {
|
|
3988
|
+
return createCofheClientBase({
|
|
3277
3989
|
config,
|
|
3278
3990
|
zkBuilderAndCrsGenerator,
|
|
3279
3991
|
tfhePublicKeyDeserializer,
|
|
@@ -3282,5 +3994,5 @@ function createCofhesdkClient(config) {
|
|
|
3282
3994
|
});
|
|
3283
3995
|
}
|
|
3284
3996
|
|
|
3285
|
-
exports.
|
|
3286
|
-
exports.
|
|
3997
|
+
exports.createCofheClient = createCofheClient;
|
|
3998
|
+
exports.createCofheConfig = createCofheConfig;
|