@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/web.cjs
CHANGED
|
@@ -38,7 +38,7 @@ var init__default = /*#__PURE__*/_interopDefault(init);
|
|
|
38
38
|
// core/client.ts
|
|
39
39
|
|
|
40
40
|
// core/error.ts
|
|
41
|
-
var
|
|
41
|
+
var CofheError = class _CofheError extends Error {
|
|
42
42
|
code;
|
|
43
43
|
cause;
|
|
44
44
|
hint;
|
|
@@ -46,25 +46,25 @@ var CofhesdkError = class _CofhesdkError extends Error {
|
|
|
46
46
|
constructor({ code, message, cause, hint, context }) {
|
|
47
47
|
const fullMessage = cause ? `${message} | Caused by: ${cause.message}` : message;
|
|
48
48
|
super(fullMessage);
|
|
49
|
-
this.name = "
|
|
49
|
+
this.name = "CofheError";
|
|
50
50
|
this.code = code;
|
|
51
51
|
this.cause = cause;
|
|
52
52
|
this.hint = hint;
|
|
53
53
|
this.context = context;
|
|
54
54
|
if (Error.captureStackTrace) {
|
|
55
|
-
Error.captureStackTrace(this,
|
|
55
|
+
Error.captureStackTrace(this, _CofheError);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* Creates a
|
|
60
|
-
* If the error is a
|
|
61
|
-
* If a wrapperError is provided, it is used to create the new
|
|
59
|
+
* Creates a CofheError from an unknown error
|
|
60
|
+
* If the error is a CofheError, it is returned unchanged, else a new CofheError is created
|
|
61
|
+
* If a wrapperError is provided, it is used to create the new CofheError, else a default is used
|
|
62
62
|
*/
|
|
63
63
|
static fromError(error, wrapperError) {
|
|
64
|
-
if (
|
|
64
|
+
if (isCofheError(error))
|
|
65
65
|
return error;
|
|
66
66
|
const cause = error instanceof Error ? error : new Error(`${error}`);
|
|
67
|
-
return new
|
|
67
|
+
return new _CofheError({
|
|
68
68
|
code: wrapperError?.code ?? "INTERNAL_ERROR" /* InternalError */,
|
|
69
69
|
message: wrapperError?.message ?? "An internal error occurred",
|
|
70
70
|
hint: wrapperError?.hint,
|
|
@@ -124,7 +124,7 @@ var bigintSafeJsonStringify = (value) => {
|
|
|
124
124
|
return value2;
|
|
125
125
|
});
|
|
126
126
|
};
|
|
127
|
-
var
|
|
127
|
+
var isCofheError = (error) => error instanceof CofheError;
|
|
128
128
|
|
|
129
129
|
// core/types.ts
|
|
130
130
|
var FheUintUTypes = [
|
|
@@ -168,14 +168,14 @@ async function getPublicClientChainID(publicClient) {
|
|
|
168
168
|
try {
|
|
169
169
|
chainId = publicClient.chain?.id ?? await publicClient.getChainId();
|
|
170
170
|
} catch (e) {
|
|
171
|
-
throw new
|
|
171
|
+
throw new CofheError({
|
|
172
172
|
code: "PUBLIC_WALLET_GET_CHAIN_ID_FAILED" /* PublicWalletGetChainIdFailed */,
|
|
173
173
|
message: "getting chain ID from public client failed",
|
|
174
174
|
cause: e instanceof Error ? e : void 0
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
177
|
if (chainId === null) {
|
|
178
|
-
throw new
|
|
178
|
+
throw new CofheError({
|
|
179
179
|
code: "PUBLIC_WALLET_GET_CHAIN_ID_FAILED" /* PublicWalletGetChainIdFailed */,
|
|
180
180
|
message: "chain ID from public client is null"
|
|
181
181
|
});
|
|
@@ -190,14 +190,14 @@ async function getWalletClientAccount(walletClient) {
|
|
|
190
190
|
address = (await walletClient.getAddresses())?.[0];
|
|
191
191
|
}
|
|
192
192
|
} catch (e) {
|
|
193
|
-
throw new
|
|
193
|
+
throw new CofheError({
|
|
194
194
|
code: "PUBLIC_WALLET_GET_ADDRESSES_FAILED" /* PublicWalletGetAddressesFailed */,
|
|
195
195
|
message: "getting address from wallet client failed",
|
|
196
196
|
cause: e instanceof Error ? e : void 0
|
|
197
197
|
});
|
|
198
198
|
}
|
|
199
199
|
if (!address) {
|
|
200
|
-
throw new
|
|
200
|
+
throw new CofheError({
|
|
201
201
|
code: "PUBLIC_WALLET_GET_ADDRESSES_FAILED" /* PublicWalletGetAddressesFailed */,
|
|
202
202
|
message: "address from wallet client is null"
|
|
203
203
|
});
|
|
@@ -301,7 +301,7 @@ var zkPack = (items, builder) => {
|
|
|
301
301
|
break;
|
|
302
302
|
}
|
|
303
303
|
default: {
|
|
304
|
-
throw new
|
|
304
|
+
throw new CofheError({
|
|
305
305
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
306
306
|
message: `Invalid utype: ${item.utype}`,
|
|
307
307
|
hint: `Ensure that the utype is valid, using the Encryptable type, for example: Encryptable.uint128(100n)`,
|
|
@@ -313,7 +313,7 @@ var zkPack = (items, builder) => {
|
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
315
|
if (totalBits > MAX_ENCRYPTABLE_BITS) {
|
|
316
|
-
throw new
|
|
316
|
+
throw new CofheError({
|
|
317
317
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
318
318
|
message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
|
|
319
319
|
hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
|
|
@@ -377,14 +377,14 @@ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chain
|
|
|
377
377
|
});
|
|
378
378
|
if (!response.ok) {
|
|
379
379
|
const errorBody = await response.text();
|
|
380
|
-
throw new
|
|
380
|
+
throw new CofheError({
|
|
381
381
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
382
382
|
message: `HTTP error! ZK proof verification failed - ${errorBody}`
|
|
383
383
|
});
|
|
384
384
|
}
|
|
385
385
|
const json = await response.json();
|
|
386
386
|
if (json.status !== "success") {
|
|
387
|
-
throw new
|
|
387
|
+
throw new CofheError({
|
|
388
388
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
389
389
|
message: `ZK proof verification response malformed - ${json.error}`
|
|
390
390
|
});
|
|
@@ -396,7 +396,7 @@ var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chain
|
|
|
396
396
|
};
|
|
397
397
|
});
|
|
398
398
|
} catch (e) {
|
|
399
|
-
throw new
|
|
399
|
+
throw new CofheError({
|
|
400
400
|
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
401
401
|
message: `ZK proof verification failed`,
|
|
402
402
|
cause: e instanceof Error ? e : void 0
|
|
@@ -514,8 +514,15 @@ var MockZkVerifierAbi = [
|
|
|
514
514
|
},
|
|
515
515
|
{ type: "error", name: "InvalidInputs", inputs: [] }
|
|
516
516
|
];
|
|
517
|
-
|
|
517
|
+
|
|
518
|
+
// core/consts.ts
|
|
519
|
+
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
520
|
+
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
521
|
+
var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
518
522
|
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
523
|
+
var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
|
|
524
|
+
|
|
525
|
+
// core/encrypt/cofheMocksZkVerifySign.ts
|
|
519
526
|
function createMockZkVerifierSigner() {
|
|
520
527
|
return viem.createWalletClient({
|
|
521
528
|
chain: chains.hardhat,
|
|
@@ -558,7 +565,7 @@ async function cofheMocksCheckEncryptableBits(items) {
|
|
|
558
565
|
}
|
|
559
566
|
}
|
|
560
567
|
if (totalBits > MAX_ENCRYPTABLE_BITS) {
|
|
561
|
-
throw new
|
|
568
|
+
throw new CofheError({
|
|
562
569
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
563
570
|
message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
|
|
564
571
|
hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
|
|
@@ -581,18 +588,18 @@ async function calcCtHashes(items, account, securityZone, publicClient) {
|
|
|
581
588
|
let ctHashes;
|
|
582
589
|
try {
|
|
583
590
|
ctHashes = await publicClient.readContract({
|
|
584
|
-
address:
|
|
591
|
+
address: MOCKS_ZK_VERIFIER_ADDRESS,
|
|
585
592
|
abi: MockZkVerifierAbi,
|
|
586
593
|
functionName: "zkVerifyCalcCtHashesPacked",
|
|
587
594
|
args: calcCtHashesArgs
|
|
588
595
|
});
|
|
589
596
|
} catch (err) {
|
|
590
|
-
throw new
|
|
597
|
+
throw new CofheError({
|
|
591
598
|
code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
|
|
592
599
|
message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
|
|
593
600
|
cause: err instanceof Error ? err : void 0,
|
|
594
601
|
context: {
|
|
595
|
-
address:
|
|
602
|
+
address: MOCKS_ZK_VERIFIER_ADDRESS,
|
|
596
603
|
items,
|
|
597
604
|
account,
|
|
598
605
|
securityZone,
|
|
@@ -602,7 +609,7 @@ async function calcCtHashes(items, account, securityZone, publicClient) {
|
|
|
602
609
|
});
|
|
603
610
|
}
|
|
604
611
|
if (ctHashes.length !== items.length) {
|
|
605
|
-
throw new
|
|
612
|
+
throw new CofheError({
|
|
606
613
|
code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
|
|
607
614
|
message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
|
|
608
615
|
context: {
|
|
@@ -625,7 +632,7 @@ async function insertCtHashes(items, walletClient) {
|
|
|
625
632
|
try {
|
|
626
633
|
const account = walletClient.account;
|
|
627
634
|
await walletClient.writeContract({
|
|
628
|
-
address:
|
|
635
|
+
address: MOCKS_ZK_VERIFIER_ADDRESS,
|
|
629
636
|
abi: MockZkVerifierAbi,
|
|
630
637
|
functionName: "insertPackedCtHashes",
|
|
631
638
|
args: insertPackedCtHashesArgs,
|
|
@@ -633,7 +640,7 @@ async function insertCtHashes(items, walletClient) {
|
|
|
633
640
|
account
|
|
634
641
|
});
|
|
635
642
|
} catch (err) {
|
|
636
|
-
throw new
|
|
643
|
+
throw new CofheError({
|
|
637
644
|
code: "ZK_MOCKS_INSERT_CT_HASHES_FAILED" /* ZkMocksInsertCtHashesFailed */,
|
|
638
645
|
message: `mockZkVerifySign insertPackedCtHashes failed while calling insertPackedCtHashes`,
|
|
639
646
|
cause: err instanceof Error ? err : void 0,
|
|
@@ -651,7 +658,7 @@ async function createProofSignatures(items, securityZone) {
|
|
|
651
658
|
try {
|
|
652
659
|
encInputSignerClient = createMockZkVerifierSigner();
|
|
653
660
|
} catch (err) {
|
|
654
|
-
throw new
|
|
661
|
+
throw new CofheError({
|
|
655
662
|
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
656
663
|
message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
|
|
657
664
|
cause: err instanceof Error ? err : void 0,
|
|
@@ -672,7 +679,7 @@ async function createProofSignatures(items, securityZone) {
|
|
|
672
679
|
signatures.push(signature);
|
|
673
680
|
}
|
|
674
681
|
} catch (err) {
|
|
675
|
-
throw new
|
|
682
|
+
throw new CofheError({
|
|
676
683
|
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
677
684
|
message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
|
|
678
685
|
cause: err instanceof Error ? err : void 0,
|
|
@@ -683,7 +690,7 @@ async function createProofSignatures(items, securityZone) {
|
|
|
683
690
|
});
|
|
684
691
|
}
|
|
685
692
|
if (signatures.length !== items.length) {
|
|
686
|
-
throw new
|
|
693
|
+
throw new CofheError({
|
|
687
694
|
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
688
695
|
message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
|
|
689
696
|
context: {
|
|
@@ -713,21 +720,18 @@ var CofheChainSchema = zod.z.object({
|
|
|
713
720
|
/** Network identifier */
|
|
714
721
|
network: zod.z.string().min(1),
|
|
715
722
|
/** coFhe service URL */
|
|
716
|
-
coFheUrl: zod.z.
|
|
723
|
+
coFheUrl: zod.z.url(),
|
|
717
724
|
/** Verifier service URL */
|
|
718
|
-
verifierUrl: zod.z.
|
|
725
|
+
verifierUrl: zod.z.url(),
|
|
719
726
|
/** Threshold network service URL */
|
|
720
|
-
thresholdNetworkUrl: zod.z.
|
|
727
|
+
thresholdNetworkUrl: zod.z.url(),
|
|
721
728
|
/** Environment type */
|
|
722
729
|
environment: EnvironmentSchema
|
|
723
730
|
});
|
|
724
|
-
|
|
725
|
-
// chains/defineChain.ts
|
|
726
731
|
function defineChain(chainConfig) {
|
|
727
732
|
const result = CofheChainSchema.safeParse(chainConfig);
|
|
728
733
|
if (!result.success) {
|
|
729
|
-
|
|
730
|
-
throw new Error(`Invalid chain configuration: ${errorMessages.join(", ")}`);
|
|
734
|
+
throw new Error(`Invalid chain configuration: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
|
|
731
735
|
}
|
|
732
736
|
return result.data;
|
|
733
737
|
}
|
|
@@ -743,43 +747,48 @@ var hardhat2 = defineChain({
|
|
|
743
747
|
thresholdNetworkUrl: "http://127.0.0.1:3000",
|
|
744
748
|
environment: "MOCK"
|
|
745
749
|
});
|
|
746
|
-
var
|
|
750
|
+
var CofheConfigSchema = zod.z.object({
|
|
747
751
|
/** Environment that the SDK is running in */
|
|
748
752
|
environment: zod.z.enum(["node", "hardhat", "web", "react"]).optional().default("node"),
|
|
749
753
|
/** List of supported chain configurations */
|
|
750
754
|
supportedChains: zod.z.array(zod.z.custom()),
|
|
751
|
-
/** How permits are generated */
|
|
752
|
-
permitGeneration: zod.z.enum(["ON_CONNECT", "ON_DECRYPT_HANDLES", "MANUAL"]).optional().default("ON_CONNECT"),
|
|
753
755
|
/** Default permit expiration in seconds, default is 30 days */
|
|
754
756
|
defaultPermitExpiration: zod.z.number().optional().default(60 * 60 * 24 * 30),
|
|
755
757
|
/** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
|
|
756
758
|
fheKeyStorage: zod.z.object({
|
|
757
|
-
getItem: zod.z.
|
|
758
|
-
|
|
759
|
-
|
|
759
|
+
getItem: zod.z.custom((val) => typeof val === "function", {
|
|
760
|
+
message: "getItem must be a function"
|
|
761
|
+
}),
|
|
762
|
+
setItem: zod.z.custom((val) => typeof val === "function", {
|
|
763
|
+
message: "setItem must be a function"
|
|
764
|
+
}),
|
|
765
|
+
removeItem: zod.z.custom((val) => typeof val === "function", {
|
|
766
|
+
message: "removeItem must be a function"
|
|
767
|
+
})
|
|
760
768
|
}).or(zod.z.null()).default(null),
|
|
761
769
|
/** Whether to use Web Workers for ZK proof generation (web platform only) */
|
|
762
770
|
useWorkers: zod.z.boolean().optional().default(true),
|
|
763
771
|
/** Mocks configs */
|
|
764
772
|
mocks: zod.z.object({
|
|
765
|
-
|
|
766
|
-
|
|
773
|
+
decryptDelay: zod.z.number().optional().default(0),
|
|
774
|
+
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])
|
|
775
|
+
}).optional().default({ decryptDelay: 0, encryptDelay: [100, 100, 100, 500, 500] }),
|
|
767
776
|
/** Internal configuration */
|
|
768
777
|
_internal: zod.z.object({
|
|
769
778
|
zkvWalletClient: zod.z.any().optional()
|
|
770
779
|
}).optional()
|
|
771
780
|
});
|
|
772
|
-
function
|
|
773
|
-
const result =
|
|
781
|
+
function createCofheConfigBase(config) {
|
|
782
|
+
const result = CofheConfigSchema.safeParse(config);
|
|
774
783
|
if (!result.success) {
|
|
775
|
-
throw new Error(`Invalid
|
|
784
|
+
throw new Error(`Invalid cofhe configuration: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
|
|
776
785
|
}
|
|
777
786
|
return result.data;
|
|
778
787
|
}
|
|
779
788
|
function getSupportedChainOrThrow(config, chainId) {
|
|
780
789
|
const supportedChain = config.supportedChains.find((chain) => chain.id === chainId);
|
|
781
790
|
if (!supportedChain) {
|
|
782
|
-
throw new
|
|
791
|
+
throw new CofheError({
|
|
783
792
|
code: "UNSUPPORTED_CHAIN" /* UnsupportedChain */,
|
|
784
793
|
message: `Config does not support chain <${chainId}>`,
|
|
785
794
|
hint: "Ensure config passed to client has been created with this chain in the config.supportedChains array.",
|
|
@@ -795,7 +804,7 @@ function getCoFheUrlOrThrow(config, chainId) {
|
|
|
795
804
|
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
796
805
|
const url = supportedChain.coFheUrl;
|
|
797
806
|
if (!url) {
|
|
798
|
-
throw new
|
|
807
|
+
throw new CofheError({
|
|
799
808
|
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
800
809
|
message: `CoFHE URL is not configured for chain <${chainId}>`,
|
|
801
810
|
hint: "Ensure this chain config includes a coFheUrl property.",
|
|
@@ -808,7 +817,7 @@ function getZkVerifierUrlOrThrow(config, chainId) {
|
|
|
808
817
|
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
809
818
|
const url = supportedChain.verifierUrl;
|
|
810
819
|
if (!url) {
|
|
811
|
-
throw new
|
|
820
|
+
throw new CofheError({
|
|
812
821
|
code: "ZK_VERIFIER_URL_UNINITIALIZED" /* ZkVerifierUrlUninitialized */,
|
|
813
822
|
message: `ZK verifier URL is not configured for chain <${chainId}>`,
|
|
814
823
|
hint: "Ensure this chain config includes a verifierUrl property.",
|
|
@@ -821,7 +830,7 @@ function getThresholdNetworkUrlOrThrow(config, chainId) {
|
|
|
821
830
|
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
822
831
|
const url = supportedChain.thresholdNetworkUrl;
|
|
823
832
|
if (!url) {
|
|
824
|
-
throw new
|
|
833
|
+
throw new CofheError({
|
|
825
834
|
code: "THRESHOLD_NETWORK_URL_UNINITIALIZED" /* ThresholdNetworkUrlUninitialized */,
|
|
826
835
|
message: `Threshold network URL is not configured for chain <${chainId}>`,
|
|
827
836
|
hint: "Ensure this chain config includes a thresholdNetworkUrl property.",
|
|
@@ -1033,7 +1042,7 @@ var BaseBuilder = class {
|
|
|
1033
1042
|
account;
|
|
1034
1043
|
constructor(params) {
|
|
1035
1044
|
if (!params.config) {
|
|
1036
|
-
throw new
|
|
1045
|
+
throw new CofheError({
|
|
1037
1046
|
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
1038
1047
|
message: "Builder config is undefined",
|
|
1039
1048
|
hint: "Ensure client has been created with a config.",
|
|
@@ -1051,12 +1060,12 @@ var BaseBuilder = class {
|
|
|
1051
1060
|
}
|
|
1052
1061
|
/**
|
|
1053
1062
|
* Asserts that this.chainId is populated
|
|
1054
|
-
* @throws {
|
|
1063
|
+
* @throws {CofheError} If chainId is not set
|
|
1055
1064
|
*/
|
|
1056
1065
|
assertChainId() {
|
|
1057
1066
|
if (this.chainId)
|
|
1058
1067
|
return;
|
|
1059
|
-
throw new
|
|
1068
|
+
throw new CofheError({
|
|
1060
1069
|
code: "CHAIN_ID_UNINITIALIZED" /* ChainIdUninitialized */,
|
|
1061
1070
|
message: "Chain ID is not set",
|
|
1062
1071
|
hint: "Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.",
|
|
@@ -1067,12 +1076,12 @@ var BaseBuilder = class {
|
|
|
1067
1076
|
}
|
|
1068
1077
|
/**
|
|
1069
1078
|
* Asserts that this.account is populated
|
|
1070
|
-
* @throws {
|
|
1079
|
+
* @throws {CofheError} If account is not set
|
|
1071
1080
|
*/
|
|
1072
1081
|
assertAccount() {
|
|
1073
1082
|
if (this.account)
|
|
1074
1083
|
return;
|
|
1075
|
-
throw new
|
|
1084
|
+
throw new CofheError({
|
|
1076
1085
|
code: "ACCOUNT_UNINITIALIZED" /* AccountUninitialized */,
|
|
1077
1086
|
message: "Account is not set",
|
|
1078
1087
|
hint: "Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.",
|
|
@@ -1083,12 +1092,12 @@ var BaseBuilder = class {
|
|
|
1083
1092
|
}
|
|
1084
1093
|
/**
|
|
1085
1094
|
* Asserts that this.publicClient is populated
|
|
1086
|
-
* @throws {
|
|
1095
|
+
* @throws {CofheError} If publicClient is not set
|
|
1087
1096
|
*/
|
|
1088
1097
|
assertPublicClient() {
|
|
1089
1098
|
if (this.publicClient)
|
|
1090
1099
|
return;
|
|
1091
|
-
throw new
|
|
1100
|
+
throw new CofheError({
|
|
1092
1101
|
code: "MISSING_PUBLIC_CLIENT" /* MissingPublicClient */,
|
|
1093
1102
|
message: "Public client not found",
|
|
1094
1103
|
hint: "Ensure client.connect() has been called with a publicClient.",
|
|
@@ -1099,12 +1108,12 @@ var BaseBuilder = class {
|
|
|
1099
1108
|
}
|
|
1100
1109
|
/**
|
|
1101
1110
|
* Asserts that this.walletClient is populated
|
|
1102
|
-
* @throws {
|
|
1111
|
+
* @throws {CofheError} If walletClient is not set
|
|
1103
1112
|
*/
|
|
1104
1113
|
assertWalletClient() {
|
|
1105
1114
|
if (this.walletClient)
|
|
1106
1115
|
return;
|
|
1107
|
-
throw new
|
|
1116
|
+
throw new CofheError({
|
|
1108
1117
|
code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
|
|
1109
1118
|
message: "Wallet client not found",
|
|
1110
1119
|
hint: "Ensure client.connect() has been called with a walletClient.",
|
|
@@ -1149,7 +1158,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1149
1158
|
this.securityZone = params.securityZone ?? 0;
|
|
1150
1159
|
this.zkvWalletClient = params.zkvWalletClient;
|
|
1151
1160
|
if (!params.tfhePublicKeyDeserializer) {
|
|
1152
|
-
throw new
|
|
1161
|
+
throw new CofheError({
|
|
1153
1162
|
code: "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER" /* MissingTfhePublicKeyDeserializer */,
|
|
1154
1163
|
message: "EncryptInputsBuilder tfhePublicKeyDeserializer is undefined",
|
|
1155
1164
|
hint: "Ensure client has been created with a tfhePublicKeyDeserializer.",
|
|
@@ -1160,7 +1169,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1160
1169
|
}
|
|
1161
1170
|
this.tfhePublicKeyDeserializer = params.tfhePublicKeyDeserializer;
|
|
1162
1171
|
if (!params.compactPkeCrsDeserializer) {
|
|
1163
|
-
throw new
|
|
1172
|
+
throw new CofheError({
|
|
1164
1173
|
code: "MISSING_COMPACT_PKE_CRS_DESERIALIZER" /* MissingCompactPkeCrsDeserializer */,
|
|
1165
1174
|
message: "EncryptInputsBuilder compactPkeCrsDeserializer is undefined",
|
|
1166
1175
|
hint: "Ensure client has been created with a compactPkeCrsDeserializer.",
|
|
@@ -1171,7 +1180,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1171
1180
|
}
|
|
1172
1181
|
this.compactPkeCrsDeserializer = params.compactPkeCrsDeserializer;
|
|
1173
1182
|
if (!params.zkBuilderAndCrsGenerator) {
|
|
1174
|
-
throw new
|
|
1183
|
+
throw new CofheError({
|
|
1175
1184
|
code: "MISSING_ZK_BUILDER_AND_CRS_GENERATOR" /* MissingZkBuilderAndCrsGenerator */,
|
|
1176
1185
|
message: "EncryptInputsBuilder zkBuilderAndCrsGenerator is undefined",
|
|
1177
1186
|
hint: "Ensure client has been created with a zkBuilderAndCrsGenerator.",
|
|
@@ -1195,7 +1204,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1195
1204
|
* ```typescript
|
|
1196
1205
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1197
1206
|
* .setAccount("0x123")
|
|
1198
|
-
* .
|
|
1207
|
+
* .execute();
|
|
1199
1208
|
* ```
|
|
1200
1209
|
*
|
|
1201
1210
|
* @returns The chainable EncryptInputsBuilder instance.
|
|
@@ -1216,7 +1225,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1216
1225
|
* ```typescript
|
|
1217
1226
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1218
1227
|
* .setChainId(11155111)
|
|
1219
|
-
* .
|
|
1228
|
+
* .execute();
|
|
1220
1229
|
* ```
|
|
1221
1230
|
*
|
|
1222
1231
|
* @returns The chainable EncryptInputsBuilder instance.
|
|
@@ -1237,7 +1246,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1237
1246
|
* ```typescript
|
|
1238
1247
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1239
1248
|
* .setSecurityZone(1)
|
|
1240
|
-
* .
|
|
1249
|
+
* .execute();
|
|
1241
1250
|
* ```
|
|
1242
1251
|
*
|
|
1243
1252
|
* @returns The chainable EncryptInputsBuilder instance.
|
|
@@ -1258,7 +1267,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1258
1267
|
* ```typescript
|
|
1259
1268
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1260
1269
|
* .setUseWorker(false)
|
|
1261
|
-
* .
|
|
1270
|
+
* .execute();
|
|
1262
1271
|
* ```
|
|
1263
1272
|
*
|
|
1264
1273
|
* @returns The chainable EncryptInputsBuilder instance.
|
|
@@ -1292,13 +1301,13 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1292
1301
|
* Example:
|
|
1293
1302
|
* ```typescript
|
|
1294
1303
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1295
|
-
* .
|
|
1296
|
-
* .
|
|
1304
|
+
* .onStep((step: EncryptStep) => console.log(step))
|
|
1305
|
+
* .execute();
|
|
1297
1306
|
* ```
|
|
1298
1307
|
*
|
|
1299
1308
|
* @returns The EncryptInputsBuilder instance.
|
|
1300
1309
|
*/
|
|
1301
|
-
|
|
1310
|
+
onStep(callback) {
|
|
1302
1311
|
this.stepCallback = callback;
|
|
1303
1312
|
return this;
|
|
1304
1313
|
}
|
|
@@ -1321,7 +1330,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1321
1330
|
this.stepCallback(step, { ...context, isStart: false, isEnd: true, duration });
|
|
1322
1331
|
}
|
|
1323
1332
|
/**
|
|
1324
|
-
* zkVerifierUrl is included in the chains exported from
|
|
1333
|
+
* zkVerifierUrl is included in the chains exported from @cofhe/sdk/chains for use in CofheConfig.supportedChains
|
|
1325
1334
|
* Users should generally not set this manually.
|
|
1326
1335
|
*/
|
|
1327
1336
|
async getZkVerifierUrl() {
|
|
@@ -1329,7 +1338,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1329
1338
|
return getZkVerifierUrlOrThrow(this.config, this.chainId);
|
|
1330
1339
|
}
|
|
1331
1340
|
/**
|
|
1332
|
-
* initTfhe is a platform-specific dependency injected into core/
|
|
1341
|
+
* initTfhe is a platform-specific dependency injected into core/createCofheClientBase by web/createCofheClient and node/createCofheClient
|
|
1333
1342
|
* web/ uses zama "tfhe"
|
|
1334
1343
|
* node/ uses zama "node-tfhe"
|
|
1335
1344
|
* Users should not set this manually.
|
|
@@ -1340,7 +1349,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1340
1349
|
try {
|
|
1341
1350
|
return await this.initTfhe();
|
|
1342
1351
|
} catch (error) {
|
|
1343
|
-
throw
|
|
1352
|
+
throw CofheError.fromError(error, {
|
|
1344
1353
|
code: "INIT_TFHE_FAILED" /* InitTfheFailed */,
|
|
1345
1354
|
message: `Failed to initialize TFHE`,
|
|
1346
1355
|
context: {
|
|
@@ -1359,7 +1368,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1359
1368
|
try {
|
|
1360
1369
|
await this.keysStorage?.rehydrateKeysStore();
|
|
1361
1370
|
} catch (error) {
|
|
1362
|
-
throw
|
|
1371
|
+
throw CofheError.fromError(error, {
|
|
1363
1372
|
code: "REHYDRATE_KEYS_STORE_FAILED" /* RehydrateKeysStoreFailed */,
|
|
1364
1373
|
message: `Failed to rehydrate keys store`,
|
|
1365
1374
|
context: {
|
|
@@ -1381,7 +1390,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1381
1390
|
this.keysStorage
|
|
1382
1391
|
);
|
|
1383
1392
|
} catch (error) {
|
|
1384
|
-
throw
|
|
1393
|
+
throw CofheError.fromError(error, {
|
|
1385
1394
|
code: "FETCH_KEYS_FAILED" /* FetchKeysFailed */,
|
|
1386
1395
|
message: `Failed to fetch FHE key and CRS`,
|
|
1387
1396
|
context: {
|
|
@@ -1394,7 +1403,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1394
1403
|
});
|
|
1395
1404
|
}
|
|
1396
1405
|
if (!fheKey) {
|
|
1397
|
-
throw new
|
|
1406
|
+
throw new CofheError({
|
|
1398
1407
|
code: "MISSING_FHE_KEY" /* MissingFheKey */,
|
|
1399
1408
|
message: `FHE key not found`,
|
|
1400
1409
|
context: {
|
|
@@ -1404,7 +1413,7 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1404
1413
|
});
|
|
1405
1414
|
}
|
|
1406
1415
|
if (!crs) {
|
|
1407
|
-
throw new
|
|
1416
|
+
throw new CofheError({
|
|
1408
1417
|
code: "MISSING_CRS" /* MissingCrs */,
|
|
1409
1418
|
message: `CRS not found for chainId <${this.chainId}>`,
|
|
1410
1419
|
context: {
|
|
@@ -1414,6 +1423,17 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1414
1423
|
}
|
|
1415
1424
|
return { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE };
|
|
1416
1425
|
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Resolves the encryptDelay config into an array of 5 per-step delays.
|
|
1428
|
+
* A single number is broadcast to all steps; a tuple is used as-is.
|
|
1429
|
+
*/
|
|
1430
|
+
resolveEncryptDelays() {
|
|
1431
|
+
const encryptDelay = this.config?.mocks?.encryptDelay ?? [100, 100, 100, 500, 500];
|
|
1432
|
+
if (typeof encryptDelay === "number") {
|
|
1433
|
+
return [encryptDelay, encryptDelay, encryptDelay, encryptDelay, encryptDelay];
|
|
1434
|
+
}
|
|
1435
|
+
return encryptDelay;
|
|
1436
|
+
}
|
|
1417
1437
|
/**
|
|
1418
1438
|
* @dev Encrypt against the cofheMocks instead of CoFHE
|
|
1419
1439
|
*
|
|
@@ -1421,25 +1441,35 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1421
1441
|
* cofheMocksInsertPackedHashes - stores the ctHashes and their plaintext values for on-chain mocking of FHE operations.
|
|
1422
1442
|
* cofheMocksZkCreateProofSignatures - creates signatures to be included in the encrypted inputs. The signers address is known and verified in the mock contracts.
|
|
1423
1443
|
*/
|
|
1424
|
-
async
|
|
1444
|
+
async mocksExecute() {
|
|
1425
1445
|
this.assertAccount();
|
|
1426
1446
|
this.assertPublicClient();
|
|
1427
1447
|
this.assertWalletClient();
|
|
1448
|
+
const [initTfheDelay, fetchKeysDelay, packDelay, proveDelay, verifyDelay] = this.resolveEncryptDelays();
|
|
1428
1449
|
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
1429
|
-
await sleep(
|
|
1430
|
-
this.fireStepEnd("initTfhe" /* InitTfhe */, {
|
|
1450
|
+
await sleep(initTfheDelay);
|
|
1451
|
+
this.fireStepEnd("initTfhe" /* InitTfhe */, {
|
|
1452
|
+
tfheInitializationExecuted: false,
|
|
1453
|
+
isMocks: true,
|
|
1454
|
+
mockSleep: initTfheDelay
|
|
1455
|
+
});
|
|
1431
1456
|
this.fireStepStart("fetchKeys" /* FetchKeys */);
|
|
1432
|
-
await sleep(
|
|
1433
|
-
this.fireStepEnd("fetchKeys" /* FetchKeys */, {
|
|
1457
|
+
await sleep(fetchKeysDelay);
|
|
1458
|
+
this.fireStepEnd("fetchKeys" /* FetchKeys */, {
|
|
1459
|
+
fheKeyFetchedFromCoFHE: false,
|
|
1460
|
+
crsFetchedFromCoFHE: false,
|
|
1461
|
+
isMocks: true,
|
|
1462
|
+
mockSleep: fetchKeysDelay
|
|
1463
|
+
});
|
|
1434
1464
|
this.fireStepStart("pack" /* Pack */);
|
|
1435
1465
|
await cofheMocksCheckEncryptableBits(this.inputItems);
|
|
1436
|
-
await sleep(
|
|
1437
|
-
this.fireStepEnd("pack" /* Pack
|
|
1466
|
+
await sleep(packDelay);
|
|
1467
|
+
this.fireStepEnd("pack" /* Pack */, { isMocks: true, mockSleep: packDelay });
|
|
1438
1468
|
this.fireStepStart("prove" /* Prove */);
|
|
1439
|
-
await sleep(
|
|
1440
|
-
this.fireStepEnd("prove" /* Prove
|
|
1469
|
+
await sleep(proveDelay);
|
|
1470
|
+
this.fireStepEnd("prove" /* Prove */, { isMocks: true, mockSleep: proveDelay });
|
|
1441
1471
|
this.fireStepStart("verify" /* Verify */);
|
|
1442
|
-
await sleep(
|
|
1472
|
+
await sleep(verifyDelay);
|
|
1443
1473
|
const signedResults = await cofheMocksZkVerifySign(
|
|
1444
1474
|
this.inputItems,
|
|
1445
1475
|
this.account,
|
|
@@ -1454,13 +1484,13 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1454
1484
|
utype: this.inputItems[index].utype,
|
|
1455
1485
|
signature
|
|
1456
1486
|
}));
|
|
1457
|
-
this.fireStepEnd("verify" /* Verify
|
|
1487
|
+
this.fireStepEnd("verify" /* Verify */, { isMocks: true, mockSleep: verifyDelay });
|
|
1458
1488
|
return encryptedInputs;
|
|
1459
1489
|
}
|
|
1460
1490
|
/**
|
|
1461
1491
|
* In the production context, perform a true encryption with the CoFHE coprocessor.
|
|
1462
1492
|
*/
|
|
1463
|
-
async
|
|
1493
|
+
async productionExecute() {
|
|
1464
1494
|
this.assertAccount();
|
|
1465
1495
|
this.assertChainId();
|
|
1466
1496
|
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
@@ -1523,15 +1553,15 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1523
1553
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1524
1554
|
* .setAccount('0x123...890') // optional
|
|
1525
1555
|
* .setChainId(11155111) // optional
|
|
1526
|
-
* .
|
|
1556
|
+
* .execute(); // execute
|
|
1527
1557
|
* ```
|
|
1528
1558
|
*
|
|
1529
1559
|
* @returns The encrypted inputs.
|
|
1530
1560
|
*/
|
|
1531
|
-
async
|
|
1561
|
+
async execute() {
|
|
1532
1562
|
if (this.chainId === chains.hardhat.id)
|
|
1533
|
-
return this.
|
|
1534
|
-
return this.
|
|
1563
|
+
return this.mocksExecute();
|
|
1564
|
+
return this.productionExecute();
|
|
1535
1565
|
}
|
|
1536
1566
|
};
|
|
1537
1567
|
|
|
@@ -1582,9 +1612,6 @@ function isBigIntOrNumber(value) {
|
|
|
1582
1612
|
}
|
|
1583
1613
|
}
|
|
1584
1614
|
}
|
|
1585
|
-
function is0xPrefixed(value) {
|
|
1586
|
-
return value.startsWith("0x");
|
|
1587
|
-
}
|
|
1588
1615
|
|
|
1589
1616
|
// permits/sealing.ts
|
|
1590
1617
|
var PRIVATE_KEY_LENGTH = 64;
|
|
@@ -1672,158 +1699,137 @@ var SerializedSealingPair = zod.z.object({
|
|
|
1672
1699
|
privateKey: zod.z.string(),
|
|
1673
1700
|
publicKey: zod.z.string()
|
|
1674
1701
|
});
|
|
1702
|
+
var addressSchema = zod.z.string().refine((val) => viem.isAddress(val), {
|
|
1703
|
+
error: "Invalid address"
|
|
1704
|
+
}).transform((val) => viem.getAddress(val));
|
|
1705
|
+
var addressNotZeroSchema = addressSchema.refine((val) => val !== viem.zeroAddress, {
|
|
1706
|
+
error: "Must not be zeroAddress"
|
|
1707
|
+
});
|
|
1708
|
+
var bytesSchema = zod.z.custom(
|
|
1709
|
+
(val) => {
|
|
1710
|
+
return typeof val === "string" && viem.isHex(val);
|
|
1711
|
+
},
|
|
1712
|
+
{
|
|
1713
|
+
message: "Invalid hex value"
|
|
1714
|
+
}
|
|
1715
|
+
);
|
|
1716
|
+
var bytesNotEmptySchema = bytesSchema.refine((val) => val !== "0x", {
|
|
1717
|
+
error: "Must not be empty"
|
|
1718
|
+
});
|
|
1675
1719
|
var DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1e3) + 7 * 24 * 60 * 60;
|
|
1676
1720
|
var zPermitWithDefaults = zod.z.object({
|
|
1677
1721
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
1678
1722
|
type: zod.z.enum(["self", "sharing", "recipient"]),
|
|
1679
|
-
issuer:
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
message: "Permit recipient :: invalid address"
|
|
1687
|
-
}),
|
|
1688
|
-
validatorId: zod.z.number().optional().default(0),
|
|
1689
|
-
validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
|
|
1690
|
-
message: "Permit validatorContract :: invalid address"
|
|
1691
|
-
}),
|
|
1692
|
-
issuerSignature: zod.z.string().optional().default("0x"),
|
|
1693
|
-
recipientSignature: zod.z.string().optional().default("0x")
|
|
1723
|
+
issuer: addressNotZeroSchema,
|
|
1724
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1725
|
+
recipient: addressSchema.optional().default(viem.zeroAddress),
|
|
1726
|
+
validatorId: zod.z.int().optional().default(0),
|
|
1727
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1728
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1729
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
1694
1730
|
});
|
|
1695
1731
|
var zPermitWithSealingPair = zPermitWithDefaults.extend({
|
|
1696
1732
|
sealingPair: SerializedSealingPair.optional()
|
|
1697
1733
|
});
|
|
1698
|
-
var
|
|
1734
|
+
var ExternalValidatorRefinement = [
|
|
1699
1735
|
(data) => data.validatorId !== 0 && data.validatorContract !== viem.zeroAddress || data.validatorId === 0 && data.validatorContract === viem.zeroAddress,
|
|
1700
1736
|
{
|
|
1701
|
-
|
|
1737
|
+
error: "Permit external validator :: validatorId and validatorContract must either both be set or both be unset.",
|
|
1702
1738
|
path: ["validatorId", "validatorContract"]
|
|
1703
1739
|
}
|
|
1704
1740
|
];
|
|
1741
|
+
var RecipientRefinement = [
|
|
1742
|
+
(data) => data.issuer !== data.recipient,
|
|
1743
|
+
{
|
|
1744
|
+
error: "Sharing permit :: issuer and recipient must not be the same",
|
|
1745
|
+
path: ["issuer", "recipient"]
|
|
1746
|
+
}
|
|
1747
|
+
];
|
|
1705
1748
|
var SelfPermitOptionsValidator = zod.z.object({
|
|
1706
1749
|
type: zod.z.literal("self").optional().default("self"),
|
|
1707
|
-
issuer:
|
|
1708
|
-
message: "Self permit issuer :: invalid address"
|
|
1709
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1710
|
-
message: "Self permit issuer :: must be 0x prefixed"
|
|
1711
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1712
|
-
message: "Self permit issuer :: must not be zeroAddress"
|
|
1713
|
-
}),
|
|
1750
|
+
issuer: addressNotZeroSchema,
|
|
1714
1751
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
1715
|
-
expiration: zod.z.
|
|
1716
|
-
recipient:
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
}),
|
|
1723
|
-
validatorId: zod.z.number().optional().default(0),
|
|
1724
|
-
validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
|
|
1725
|
-
message: "Self permit validatorContract :: invalid address"
|
|
1726
|
-
}),
|
|
1727
|
-
issuerSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
1728
|
-
message: "Self permit issuerSignature :: must be 0x prefixed"
|
|
1729
|
-
}),
|
|
1730
|
-
recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
1731
|
-
message: "Self permit recipientSignature :: must be 0x prefixed"
|
|
1732
|
-
})
|
|
1733
|
-
}).refine(...ValidatorContractRefinement);
|
|
1752
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1753
|
+
recipient: addressSchema.optional().default(viem.zeroAddress),
|
|
1754
|
+
validatorId: zod.z.int().optional().default(0),
|
|
1755
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1756
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1757
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
1758
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1734
1759
|
var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "self", {
|
|
1735
|
-
|
|
1760
|
+
error: "Type must be 'self'"
|
|
1736
1761
|
}).refine((data) => data.recipient === viem.zeroAddress, {
|
|
1737
|
-
|
|
1762
|
+
error: "Recipient must be zeroAddress"
|
|
1738
1763
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
1739
|
-
|
|
1764
|
+
error: "IssuerSignature must be populated"
|
|
1740
1765
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
1741
|
-
|
|
1742
|
-
}).refine(...
|
|
1766
|
+
error: "RecipientSignature must be empty"
|
|
1767
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1743
1768
|
var SharingPermitOptionsValidator = zod.z.object({
|
|
1744
1769
|
type: zod.z.literal("sharing").optional().default("sharing"),
|
|
1745
|
-
issuer:
|
|
1746
|
-
|
|
1747
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1748
|
-
message: "Sharing permit issuer :: must be 0x prefixed"
|
|
1749
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1750
|
-
message: "Sharing permit issuer :: must not be zeroAddress"
|
|
1751
|
-
}),
|
|
1752
|
-
recipient: zod.z.string().refine((val) => viem.isAddress(val), {
|
|
1753
|
-
message: "Sharing permit recipient :: invalid address"
|
|
1754
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1755
|
-
message: "Sharing permit recipient :: must be 0x prefixed"
|
|
1756
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1757
|
-
message: "Sharing permit recipient :: must not be zeroAddress"
|
|
1758
|
-
}),
|
|
1770
|
+
issuer: addressNotZeroSchema,
|
|
1771
|
+
recipient: addressNotZeroSchema,
|
|
1759
1772
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
1760
|
-
expiration: zod.z.
|
|
1761
|
-
validatorId: zod.z.
|
|
1762
|
-
validatorContract:
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
message: "Sharing permit issuerSignature :: must be 0x prefixed"
|
|
1767
|
-
}),
|
|
1768
|
-
recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
1769
|
-
message: "Sharing permit recipientSignature :: must be 0x prefixed"
|
|
1770
|
-
})
|
|
1771
|
-
}).refine(...ValidatorContractRefinement);
|
|
1773
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
1774
|
+
validatorId: zod.z.int().optional().default(0),
|
|
1775
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1776
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
1777
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
1778
|
+
}).refine(...RecipientRefinement).refine(...ExternalValidatorRefinement);
|
|
1772
1779
|
var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "sharing", {
|
|
1773
|
-
|
|
1780
|
+
error: "Type must be 'sharing'"
|
|
1774
1781
|
}).refine((data) => data.recipient !== viem.zeroAddress, {
|
|
1775
|
-
|
|
1782
|
+
error: "Recipient must not be zeroAddress"
|
|
1776
1783
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
1777
|
-
|
|
1784
|
+
error: "IssuerSignature must be populated"
|
|
1778
1785
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
1779
|
-
|
|
1780
|
-
}).refine(...
|
|
1786
|
+
error: "RecipientSignature must be empty"
|
|
1787
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1781
1788
|
var ImportPermitOptionsValidator = zod.z.object({
|
|
1782
1789
|
type: zod.z.literal("recipient").optional().default("recipient"),
|
|
1783
|
-
issuer:
|
|
1784
|
-
|
|
1785
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1786
|
-
message: "Import permit issuer :: must be 0x prefixed"
|
|
1787
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1788
|
-
message: "Import permit issuer :: must not be zeroAddress"
|
|
1789
|
-
}),
|
|
1790
|
-
recipient: zod.z.string().refine((val) => viem.isAddress(val), {
|
|
1791
|
-
message: "Import permit recipient :: invalid address"
|
|
1792
|
-
}).refine((val) => is0xPrefixed(val), {
|
|
1793
|
-
message: "Import permit recipient :: must be 0x prefixed"
|
|
1794
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
1795
|
-
message: "Import permit recipient :: must not be zeroAddress"
|
|
1796
|
-
}),
|
|
1797
|
-
issuerSignature: zod.z.string().refine((val) => is0xPrefixed(val), {
|
|
1798
|
-
message: "Import permit issuerSignature :: must be 0x prefixed"
|
|
1799
|
-
}).refine((val) => val !== "0x", {
|
|
1800
|
-
message: "Import permit :: issuerSignature must be provided"
|
|
1801
|
-
}),
|
|
1790
|
+
issuer: addressNotZeroSchema,
|
|
1791
|
+
recipient: addressNotZeroSchema,
|
|
1802
1792
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
1803
|
-
expiration: zod.z.
|
|
1804
|
-
validatorId: zod.z.
|
|
1805
|
-
validatorContract:
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
message: "Import permit recipientSignature :: must be 0x prefixed"
|
|
1810
|
-
})
|
|
1811
|
-
}).refine(...ValidatorContractRefinement);
|
|
1793
|
+
expiration: zod.z.int(),
|
|
1794
|
+
validatorId: zod.z.int().optional().default(0),
|
|
1795
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
1796
|
+
issuerSignature: bytesNotEmptySchema,
|
|
1797
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
1798
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1812
1799
|
var ImportPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "recipient", {
|
|
1813
|
-
|
|
1800
|
+
error: "Type must be 'recipient'"
|
|
1814
1801
|
}).refine((data) => data.recipient !== viem.zeroAddress, {
|
|
1815
|
-
|
|
1802
|
+
error: "Recipient must not be zeroAddress"
|
|
1816
1803
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
1817
|
-
|
|
1804
|
+
error: "IssuerSignature must be populated"
|
|
1818
1805
|
}).refine((data) => data.recipientSignature !== "0x", {
|
|
1819
|
-
|
|
1820
|
-
}).refine(...
|
|
1821
|
-
var
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1806
|
+
error: "RecipientSignature must be populated"
|
|
1807
|
+
}).refine(...ExternalValidatorRefinement);
|
|
1808
|
+
var safeParseAndThrowFormatted = (schema, data, message) => {
|
|
1809
|
+
const result = schema.safeParse(data);
|
|
1810
|
+
if (!result.success) {
|
|
1811
|
+
throw new Error(`${message}: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
|
|
1812
|
+
}
|
|
1813
|
+
return result.data;
|
|
1814
|
+
};
|
|
1815
|
+
var validateSelfPermitOptions = (options) => {
|
|
1816
|
+
return safeParseAndThrowFormatted(SelfPermitOptionsValidator, options, "Invalid self permit options");
|
|
1817
|
+
};
|
|
1818
|
+
var validateSharingPermitOptions = (options) => {
|
|
1819
|
+
return safeParseAndThrowFormatted(SharingPermitOptionsValidator, options, "Invalid sharing permit options");
|
|
1820
|
+
};
|
|
1821
|
+
var validateImportPermitOptions = (options) => {
|
|
1822
|
+
return safeParseAndThrowFormatted(ImportPermitOptionsValidator, options, "Invalid import permit options");
|
|
1823
|
+
};
|
|
1824
|
+
var validateSelfPermit = (permit) => {
|
|
1825
|
+
return safeParseAndThrowFormatted(SelfPermitValidator, permit, "Invalid self permit");
|
|
1826
|
+
};
|
|
1827
|
+
var validateSharingPermit = (permit) => {
|
|
1828
|
+
return safeParseAndThrowFormatted(SharingPermitValidator, permit, "Invalid sharing permit");
|
|
1829
|
+
};
|
|
1830
|
+
var validateImportPermit = (permit) => {
|
|
1831
|
+
return safeParseAndThrowFormatted(ImportPermitValidator, permit, "Invalid import permit");
|
|
1832
|
+
};
|
|
1827
1833
|
var ValidationUtils = {
|
|
1828
1834
|
/**
|
|
1829
1835
|
* Check if permit is expired
|
|
@@ -1917,6 +1923,179 @@ var SignatureUtils = {
|
|
|
1917
1923
|
throw new Error(`Unknown permit type: ${permitType}`);
|
|
1918
1924
|
}
|
|
1919
1925
|
};
|
|
1926
|
+
var getAclAddress = async (publicClient) => {
|
|
1927
|
+
const ACL_IFACE = "function acl() view returns (address)";
|
|
1928
|
+
const aclAbi = viem.parseAbi([ACL_IFACE]);
|
|
1929
|
+
return await publicClient.readContract({
|
|
1930
|
+
address: TASK_MANAGER_ADDRESS,
|
|
1931
|
+
abi: aclAbi,
|
|
1932
|
+
functionName: "acl"
|
|
1933
|
+
});
|
|
1934
|
+
};
|
|
1935
|
+
var getAclEIP712Domain = async (publicClient) => {
|
|
1936
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
1937
|
+
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
1938
|
+
const domainAbi = viem.parseAbi([EIP712_DOMAIN_IFACE]);
|
|
1939
|
+
const domain = await publicClient.readContract({
|
|
1940
|
+
address: aclAddress,
|
|
1941
|
+
abi: domainAbi,
|
|
1942
|
+
functionName: "eip712Domain"
|
|
1943
|
+
});
|
|
1944
|
+
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
1945
|
+
return {
|
|
1946
|
+
name,
|
|
1947
|
+
version,
|
|
1948
|
+
chainId: Number(chainId),
|
|
1949
|
+
verifyingContract
|
|
1950
|
+
};
|
|
1951
|
+
};
|
|
1952
|
+
var checkPermitValidityOnChain = async (permission, publicClient) => {
|
|
1953
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
1954
|
+
try {
|
|
1955
|
+
await publicClient.simulateContract({
|
|
1956
|
+
address: aclAddress,
|
|
1957
|
+
abi: checkPermitValidityAbi,
|
|
1958
|
+
functionName: "checkPermitValidity",
|
|
1959
|
+
args: [
|
|
1960
|
+
{
|
|
1961
|
+
issuer: permission.issuer,
|
|
1962
|
+
expiration: BigInt(permission.expiration),
|
|
1963
|
+
recipient: permission.recipient,
|
|
1964
|
+
validatorId: BigInt(permission.validatorId),
|
|
1965
|
+
validatorContract: permission.validatorContract,
|
|
1966
|
+
sealingKey: permission.sealingKey,
|
|
1967
|
+
issuerSignature: permission.issuerSignature,
|
|
1968
|
+
recipientSignature: permission.recipientSignature
|
|
1969
|
+
}
|
|
1970
|
+
]
|
|
1971
|
+
});
|
|
1972
|
+
return true;
|
|
1973
|
+
} catch (err) {
|
|
1974
|
+
if (err instanceof viem.BaseError) {
|
|
1975
|
+
const revertError = err.walk((err2) => err2 instanceof viem.ContractFunctionRevertedError);
|
|
1976
|
+
if (revertError instanceof viem.ContractFunctionRevertedError) {
|
|
1977
|
+
const errorName = revertError.data?.errorName ?? "";
|
|
1978
|
+
throw new Error(errorName);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
const customErrorName = extractCustomErrorFromDetails(err, checkPermitValidityAbi);
|
|
1982
|
+
if (customErrorName) {
|
|
1983
|
+
throw new Error(customErrorName);
|
|
1984
|
+
}
|
|
1985
|
+
const hhDetailsData = extractReturnData(err);
|
|
1986
|
+
if (hhDetailsData != null) {
|
|
1987
|
+
const decoded = viem.decodeErrorResult({
|
|
1988
|
+
abi: checkPermitValidityAbi,
|
|
1989
|
+
data: hhDetailsData
|
|
1990
|
+
});
|
|
1991
|
+
throw new Error(decoded.errorName);
|
|
1992
|
+
}
|
|
1993
|
+
throw err;
|
|
1994
|
+
}
|
|
1995
|
+
};
|
|
1996
|
+
function extractCustomErrorFromDetails(err, abi) {
|
|
1997
|
+
const anyErr = err;
|
|
1998
|
+
const details = anyErr?.details ?? anyErr?.cause?.details;
|
|
1999
|
+
if (typeof details === "string") {
|
|
2000
|
+
const customErrorMatch = details.match(/reverted with custom error '(\w+)\(\)'/);
|
|
2001
|
+
if (customErrorMatch) {
|
|
2002
|
+
const errorName = customErrorMatch[1];
|
|
2003
|
+
const errorExists = abi.some((item) => item.type === "error" && item.name === errorName);
|
|
2004
|
+
if (errorExists) {
|
|
2005
|
+
return errorName;
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
return void 0;
|
|
2010
|
+
}
|
|
2011
|
+
function extractReturnData(err) {
|
|
2012
|
+
const anyErr = err;
|
|
2013
|
+
const s = anyErr?.details ?? anyErr?.cause?.details ?? anyErr?.shortMessage ?? anyErr?.message ?? String(err);
|
|
2014
|
+
return s.match(/return data:\s*(0x[a-fA-F0-9]+)/)?.[1];
|
|
2015
|
+
}
|
|
2016
|
+
var checkPermitValidityAbi = [
|
|
2017
|
+
{
|
|
2018
|
+
type: "function",
|
|
2019
|
+
name: "checkPermitValidity",
|
|
2020
|
+
inputs: [
|
|
2021
|
+
{
|
|
2022
|
+
name: "permission",
|
|
2023
|
+
type: "tuple",
|
|
2024
|
+
internalType: "struct Permission",
|
|
2025
|
+
components: [
|
|
2026
|
+
{
|
|
2027
|
+
name: "issuer",
|
|
2028
|
+
type: "address",
|
|
2029
|
+
internalType: "address"
|
|
2030
|
+
},
|
|
2031
|
+
{
|
|
2032
|
+
name: "expiration",
|
|
2033
|
+
type: "uint64",
|
|
2034
|
+
internalType: "uint64"
|
|
2035
|
+
},
|
|
2036
|
+
{
|
|
2037
|
+
name: "recipient",
|
|
2038
|
+
type: "address",
|
|
2039
|
+
internalType: "address"
|
|
2040
|
+
},
|
|
2041
|
+
{
|
|
2042
|
+
name: "validatorId",
|
|
2043
|
+
type: "uint256",
|
|
2044
|
+
internalType: "uint256"
|
|
2045
|
+
},
|
|
2046
|
+
{
|
|
2047
|
+
name: "validatorContract",
|
|
2048
|
+
type: "address",
|
|
2049
|
+
internalType: "address"
|
|
2050
|
+
},
|
|
2051
|
+
{
|
|
2052
|
+
name: "sealingKey",
|
|
2053
|
+
type: "bytes32",
|
|
2054
|
+
internalType: "bytes32"
|
|
2055
|
+
},
|
|
2056
|
+
{
|
|
2057
|
+
name: "issuerSignature",
|
|
2058
|
+
type: "bytes",
|
|
2059
|
+
internalType: "bytes"
|
|
2060
|
+
},
|
|
2061
|
+
{
|
|
2062
|
+
name: "recipientSignature",
|
|
2063
|
+
type: "bytes",
|
|
2064
|
+
internalType: "bytes"
|
|
2065
|
+
}
|
|
2066
|
+
]
|
|
2067
|
+
}
|
|
2068
|
+
],
|
|
2069
|
+
outputs: [
|
|
2070
|
+
{
|
|
2071
|
+
name: "",
|
|
2072
|
+
type: "bool",
|
|
2073
|
+
internalType: "bool"
|
|
2074
|
+
}
|
|
2075
|
+
],
|
|
2076
|
+
stateMutability: "view"
|
|
2077
|
+
},
|
|
2078
|
+
{
|
|
2079
|
+
type: "error",
|
|
2080
|
+
name: "PermissionInvalid_Disabled",
|
|
2081
|
+
inputs: []
|
|
2082
|
+
},
|
|
2083
|
+
{
|
|
2084
|
+
type: "error",
|
|
2085
|
+
name: "PermissionInvalid_Expired",
|
|
2086
|
+
inputs: []
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
2089
|
+
type: "error",
|
|
2090
|
+
name: "PermissionInvalid_IssuerSignature",
|
|
2091
|
+
inputs: []
|
|
2092
|
+
},
|
|
2093
|
+
{
|
|
2094
|
+
type: "error",
|
|
2095
|
+
name: "PermissionInvalid_RecipientSignature",
|
|
2096
|
+
inputs: []
|
|
2097
|
+
}
|
|
2098
|
+
];
|
|
1920
2099
|
|
|
1921
2100
|
// permits/permit.ts
|
|
1922
2101
|
var PermitUtils = {
|
|
@@ -1925,14 +2104,10 @@ var PermitUtils = {
|
|
|
1925
2104
|
*/
|
|
1926
2105
|
createSelf: (options) => {
|
|
1927
2106
|
const validation = validateSelfPermitOptions(options);
|
|
1928
|
-
if (!validation.success) {
|
|
1929
|
-
throw new Error(
|
|
1930
|
-
"PermitUtils :: createSelf :: Parsing SelfPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
1931
|
-
);
|
|
1932
|
-
}
|
|
1933
2107
|
const sealingPair = GenerateSealingKey();
|
|
1934
2108
|
const permit = {
|
|
1935
|
-
|
|
2109
|
+
hash: PermitUtils.getHash(validation),
|
|
2110
|
+
...validation,
|
|
1936
2111
|
sealingPair,
|
|
1937
2112
|
_signedDomain: void 0
|
|
1938
2113
|
};
|
|
@@ -1943,14 +2118,10 @@ var PermitUtils = {
|
|
|
1943
2118
|
*/
|
|
1944
2119
|
createSharing: (options) => {
|
|
1945
2120
|
const validation = validateSharingPermitOptions(options);
|
|
1946
|
-
if (!validation.success) {
|
|
1947
|
-
throw new Error(
|
|
1948
|
-
"PermitUtils :: createSharing :: Parsing SharingPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
1949
|
-
);
|
|
1950
|
-
}
|
|
1951
2121
|
const sealingPair = GenerateSealingKey();
|
|
1952
2122
|
const permit = {
|
|
1953
|
-
|
|
2123
|
+
hash: PermitUtils.getHash(validation),
|
|
2124
|
+
...validation,
|
|
1954
2125
|
sealingPair,
|
|
1955
2126
|
_signedDomain: void 0
|
|
1956
2127
|
};
|
|
@@ -1965,27 +2136,21 @@ var PermitUtils = {
|
|
|
1965
2136
|
try {
|
|
1966
2137
|
parsedOptions = JSON.parse(options);
|
|
1967
2138
|
} catch (error) {
|
|
1968
|
-
throw new Error(`
|
|
2139
|
+
throw new Error(`Failed to parse JSON string: ${error}`);
|
|
1969
2140
|
}
|
|
1970
2141
|
} else if (typeof options === "object" && options !== null) {
|
|
1971
2142
|
parsedOptions = options;
|
|
1972
2143
|
} else {
|
|
1973
|
-
throw new Error(
|
|
1974
|
-
"PermitUtils :: importShared :: Invalid input type, expected ImportSharedPermitOptions, object, or string"
|
|
1975
|
-
);
|
|
2144
|
+
throw new Error("Invalid input type, expected ImportSharedPermitOptions, object, or string");
|
|
1976
2145
|
}
|
|
1977
2146
|
if (parsedOptions.type != null && parsedOptions.type !== "sharing") {
|
|
1978
|
-
throw new Error(`
|
|
2147
|
+
throw new Error(`Invalid permit type <${parsedOptions.type}>, must be "sharing"`);
|
|
1979
2148
|
}
|
|
1980
2149
|
const validation = validateImportPermitOptions({ ...parsedOptions, type: "recipient" });
|
|
1981
|
-
if (!validation.success) {
|
|
1982
|
-
throw new Error(
|
|
1983
|
-
"PermitUtils :: importShared :: Parsing ImportPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
1984
|
-
);
|
|
1985
|
-
}
|
|
1986
2150
|
const sealingPair = GenerateSealingKey();
|
|
1987
2151
|
const permit = {
|
|
1988
|
-
|
|
2152
|
+
hash: PermitUtils.getHash(validation),
|
|
2153
|
+
...validation,
|
|
1989
2154
|
sealingPair,
|
|
1990
2155
|
_signedDomain: void 0
|
|
1991
2156
|
};
|
|
@@ -1997,11 +2162,11 @@ var PermitUtils = {
|
|
|
1997
2162
|
sign: async (permit, publicClient, walletClient) => {
|
|
1998
2163
|
if (walletClient == null || walletClient.account == null) {
|
|
1999
2164
|
throw new Error(
|
|
2000
|
-
"
|
|
2165
|
+
"Missing walletClient, you must pass in a `walletClient` for the connected user to create a permit signature"
|
|
2001
2166
|
);
|
|
2002
2167
|
}
|
|
2003
2168
|
const primaryType = SignatureUtils.getPrimaryType(permit.type);
|
|
2004
|
-
const domain = await
|
|
2169
|
+
const domain = await getAclEIP712Domain(publicClient);
|
|
2005
2170
|
const { types, message } = SignatureUtils.getSignatureParams(PermitUtils.getPermission(permit, true), primaryType);
|
|
2006
2171
|
const signature = await walletClient.signTypedData({
|
|
2007
2172
|
domain,
|
|
@@ -2061,6 +2226,7 @@ var PermitUtils = {
|
|
|
2061
2226
|
*/
|
|
2062
2227
|
serialize: (permit) => {
|
|
2063
2228
|
return {
|
|
2229
|
+
hash: permit.hash,
|
|
2064
2230
|
name: permit.name,
|
|
2065
2231
|
type: permit.type,
|
|
2066
2232
|
issuer: permit.issuer,
|
|
@@ -2085,7 +2251,7 @@ var PermitUtils = {
|
|
|
2085
2251
|
} else if (permit.type === "recipient") {
|
|
2086
2252
|
return validateImportPermit(permit);
|
|
2087
2253
|
} else {
|
|
2088
|
-
throw new Error("
|
|
2254
|
+
throw new Error("Invalid permit type");
|
|
2089
2255
|
}
|
|
2090
2256
|
},
|
|
2091
2257
|
/**
|
|
@@ -2093,12 +2259,7 @@ var PermitUtils = {
|
|
|
2093
2259
|
*/
|
|
2094
2260
|
getPermission: (permit, skipValidation = false) => {
|
|
2095
2261
|
if (!skipValidation) {
|
|
2096
|
-
|
|
2097
|
-
if (!validationResult.success) {
|
|
2098
|
-
throw new Error(
|
|
2099
|
-
`PermitUtils :: getPermission :: permit validation failed - ${JSON.stringify(validationResult.error, null, 2)} ${JSON.stringify(permit, null, 2)}`
|
|
2100
|
-
);
|
|
2101
|
-
}
|
|
2262
|
+
PermitUtils.validate(permit);
|
|
2102
2263
|
}
|
|
2103
2264
|
return {
|
|
2104
2265
|
issuer: permit.issuer,
|
|
@@ -2179,28 +2340,7 @@ var PermitUtils = {
|
|
|
2179
2340
|
* Fetch EIP712 domain from the blockchain
|
|
2180
2341
|
*/
|
|
2181
2342
|
fetchEIP712Domain: async (publicClient) => {
|
|
2182
|
-
|
|
2183
|
-
const ACL_IFACE = "function acl() view returns (address)";
|
|
2184
|
-
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
2185
|
-
const aclAbi = viem.parseAbi([ACL_IFACE]);
|
|
2186
|
-
const aclAddress = await publicClient.readContract({
|
|
2187
|
-
address: TASK_MANAGER_ADDRESS,
|
|
2188
|
-
abi: aclAbi,
|
|
2189
|
-
functionName: "acl"
|
|
2190
|
-
});
|
|
2191
|
-
const domainAbi = viem.parseAbi([EIP712_DOMAIN_IFACE]);
|
|
2192
|
-
const domain = await publicClient.readContract({
|
|
2193
|
-
address: aclAddress,
|
|
2194
|
-
abi: domainAbi,
|
|
2195
|
-
functionName: "eip712Domain"
|
|
2196
|
-
});
|
|
2197
|
-
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
2198
|
-
return {
|
|
2199
|
-
name,
|
|
2200
|
-
version,
|
|
2201
|
-
chainId: Number(chainId),
|
|
2202
|
-
verifyingContract
|
|
2203
|
-
};
|
|
2343
|
+
return getAclEIP712Domain(publicClient);
|
|
2204
2344
|
},
|
|
2205
2345
|
/**
|
|
2206
2346
|
* Check if permit's signed domain matches the provided domain
|
|
@@ -2214,8 +2354,15 @@ var PermitUtils = {
|
|
|
2214
2354
|
checkSignedDomainValid: async (permit, publicClient) => {
|
|
2215
2355
|
if (permit._signedDomain == null)
|
|
2216
2356
|
return false;
|
|
2217
|
-
const domain = await
|
|
2357
|
+
const domain = await getAclEIP712Domain(publicClient);
|
|
2218
2358
|
return PermitUtils.matchesDomain(permit, domain);
|
|
2359
|
+
},
|
|
2360
|
+
/**
|
|
2361
|
+
* Check if permit passes the on-chain validation
|
|
2362
|
+
*/
|
|
2363
|
+
checkValidityOnChain: async (permit, publicClient) => {
|
|
2364
|
+
const permission = PermitUtils.getPermission(permit);
|
|
2365
|
+
return checkPermitValidityOnChain(permission, publicClient);
|
|
2219
2366
|
}
|
|
2220
2367
|
};
|
|
2221
2368
|
var PERMIT_STORE_DEFAULTS = {
|
|
@@ -2269,11 +2416,11 @@ var setPermit = (chainId, account, permit) => {
|
|
|
2269
2416
|
state.permits[chainId] = {};
|
|
2270
2417
|
if (state.permits[chainId][account] == null)
|
|
2271
2418
|
state.permits[chainId][account] = {};
|
|
2272
|
-
state.permits[chainId][account][
|
|
2419
|
+
state.permits[chainId][account][permit.hash] = PermitUtils.serialize(permit);
|
|
2273
2420
|
})
|
|
2274
2421
|
);
|
|
2275
2422
|
};
|
|
2276
|
-
var removePermit = (chainId, account, hash
|
|
2423
|
+
var removePermit = (chainId, account, hash) => {
|
|
2277
2424
|
clearStaleStore();
|
|
2278
2425
|
_permitStore.setState(
|
|
2279
2426
|
immer.produce((state) => {
|
|
@@ -2287,15 +2434,7 @@ var removePermit = (chainId, account, hash, force) => {
|
|
|
2287
2434
|
if (accountPermits[hash] == null)
|
|
2288
2435
|
return;
|
|
2289
2436
|
if (state.activePermitHash[chainId][account] === hash) {
|
|
2290
|
-
|
|
2291
|
-
if (otherPermitHash) {
|
|
2292
|
-
state.activePermitHash[chainId][account] = otherPermitHash;
|
|
2293
|
-
} else {
|
|
2294
|
-
if (!force) {
|
|
2295
|
-
throw new Error("Cannot remove the last permit without force flag");
|
|
2296
|
-
}
|
|
2297
|
-
state.activePermitHash[chainId][account] = void 0;
|
|
2298
|
-
}
|
|
2437
|
+
state.activePermitHash[chainId][account] = void 0;
|
|
2299
2438
|
}
|
|
2300
2439
|
accountPermits[hash] = void 0;
|
|
2301
2440
|
})
|
|
@@ -2346,7 +2485,7 @@ var storeActivePermit = async (permit, publicClient, walletClient) => {
|
|
|
2346
2485
|
const chainId = await publicClient.getChainId();
|
|
2347
2486
|
const account = walletClient.account.address;
|
|
2348
2487
|
permitStore.setPermit(chainId, account, permit);
|
|
2349
|
-
permitStore.setActivePermitHash(chainId, account,
|
|
2488
|
+
permitStore.setActivePermitHash(chainId, account, permit.hash);
|
|
2350
2489
|
};
|
|
2351
2490
|
var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
|
|
2352
2491
|
const permit = await permitMethod(options, publicClient, walletClient);
|
|
@@ -2404,7 +2543,7 @@ var getOrCreateSharingPermit = async (publicClient, walletClient, options, chain
|
|
|
2404
2543
|
}
|
|
2405
2544
|
return createSharing(options, publicClient, walletClient);
|
|
2406
2545
|
};
|
|
2407
|
-
var removePermit2 = async (chainId, account, hash
|
|
2546
|
+
var removePermit2 = async (chainId, account, hash) => permitStore.removePermit(chainId, account, hash);
|
|
2408
2547
|
var removeActivePermit = async (chainId, account) => permitStore.removeActivePermitHash(chainId, account);
|
|
2409
2548
|
var permits = {
|
|
2410
2549
|
getSnapshot: permitStore.store.getState,
|
|
@@ -2444,8 +2583,8 @@ var convertViaUtype = (utype, value) => {
|
|
|
2444
2583
|
}
|
|
2445
2584
|
};
|
|
2446
2585
|
|
|
2447
|
-
// core/decrypt/
|
|
2448
|
-
var
|
|
2586
|
+
// core/decrypt/MockThresholdNetworkAbi.ts
|
|
2587
|
+
var MockThresholdNetworkAbi = [
|
|
2449
2588
|
{
|
|
2450
2589
|
type: "function",
|
|
2451
2590
|
name: "acl",
|
|
@@ -2492,11 +2631,7 @@ var MockQueryDecrypterAbi = [
|
|
|
2492
2631
|
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2493
2632
|
{ name: "recipient", type: "address", internalType: "address" },
|
|
2494
2633
|
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
2495
|
-
{
|
|
2496
|
-
name: "validatorContract",
|
|
2497
|
-
type: "address",
|
|
2498
|
-
internalType: "address"
|
|
2499
|
-
},
|
|
2634
|
+
{ name: "validatorContract", type: "address", internalType: "address" },
|
|
2500
2635
|
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2501
2636
|
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2502
2637
|
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
@@ -2525,11 +2660,7 @@ var MockQueryDecrypterAbi = [
|
|
|
2525
2660
|
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2526
2661
|
{ name: "recipient", type: "address", internalType: "address" },
|
|
2527
2662
|
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
2528
|
-
{
|
|
2529
|
-
name: "validatorContract",
|
|
2530
|
-
type: "address",
|
|
2531
|
-
internalType: "address"
|
|
2532
|
-
},
|
|
2663
|
+
{ name: "validatorContract", type: "address", internalType: "address" },
|
|
2533
2664
|
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2534
2665
|
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2535
2666
|
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
@@ -2553,13 +2684,6 @@ var MockQueryDecrypterAbi = [
|
|
|
2553
2684
|
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
2554
2685
|
stateMutability: "pure"
|
|
2555
2686
|
},
|
|
2556
|
-
{
|
|
2557
|
-
type: "function",
|
|
2558
|
-
name: "taskManager",
|
|
2559
|
-
inputs: [],
|
|
2560
|
-
outputs: [{ name: "", type: "address", internalType: "contract TaskManager" }],
|
|
2561
|
-
stateMutability: "view"
|
|
2562
|
-
},
|
|
2563
2687
|
{
|
|
2564
2688
|
type: "function",
|
|
2565
2689
|
name: "unseal",
|
|
@@ -2570,16 +2694,80 @@ var MockQueryDecrypterAbi = [
|
|
|
2570
2694
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
2571
2695
|
stateMutability: "pure"
|
|
2572
2696
|
},
|
|
2573
|
-
{
|
|
2574
|
-
|
|
2575
|
-
|
|
2697
|
+
{
|
|
2698
|
+
type: "function",
|
|
2699
|
+
name: "mockAcl",
|
|
2700
|
+
inputs: [],
|
|
2701
|
+
outputs: [{ name: "", type: "address", internalType: "contract MockACL" }],
|
|
2702
|
+
stateMutability: "view"
|
|
2703
|
+
},
|
|
2704
|
+
{
|
|
2705
|
+
type: "function",
|
|
2706
|
+
name: "mockTaskManager",
|
|
2707
|
+
inputs: [],
|
|
2708
|
+
outputs: [{ name: "", type: "address", internalType: "contract MockTaskManager" }],
|
|
2709
|
+
stateMutability: "view"
|
|
2710
|
+
},
|
|
2711
|
+
{
|
|
2712
|
+
type: "function",
|
|
2713
|
+
name: "mockQueryDecrypt",
|
|
2714
|
+
inputs: [
|
|
2715
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
2716
|
+
{ name: "", type: "uint256", internalType: "uint256" },
|
|
2717
|
+
{ name: "issuer", type: "address", internalType: "address" }
|
|
2718
|
+
],
|
|
2719
|
+
outputs: [
|
|
2720
|
+
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
2721
|
+
{ name: "error", type: "string", internalType: "string" },
|
|
2722
|
+
{ name: "", type: "uint256", internalType: "uint256" }
|
|
2723
|
+
],
|
|
2724
|
+
stateMutability: "view"
|
|
2725
|
+
},
|
|
2726
|
+
{
|
|
2727
|
+
type: "function",
|
|
2728
|
+
name: "decryptForTxWithPermit",
|
|
2729
|
+
inputs: [
|
|
2730
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
2731
|
+
{
|
|
2732
|
+
name: "permission",
|
|
2733
|
+
type: "tuple",
|
|
2734
|
+
internalType: "struct Permission",
|
|
2735
|
+
components: [
|
|
2736
|
+
{ name: "issuer", type: "address", internalType: "address" },
|
|
2737
|
+
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
2738
|
+
{ name: "recipient", type: "address", internalType: "address" },
|
|
2739
|
+
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
2740
|
+
{ name: "validatorContract", type: "address", internalType: "address" },
|
|
2741
|
+
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
2742
|
+
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
2743
|
+
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
2744
|
+
]
|
|
2745
|
+
}
|
|
2746
|
+
],
|
|
2747
|
+
outputs: [
|
|
2748
|
+
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
2749
|
+
{ name: "error", type: "string", internalType: "string" },
|
|
2750
|
+
{ name: "decryptedValue", type: "uint256", internalType: "uint256" }
|
|
2751
|
+
],
|
|
2752
|
+
stateMutability: "view"
|
|
2753
|
+
},
|
|
2754
|
+
{
|
|
2755
|
+
type: "function",
|
|
2756
|
+
name: "decryptForTxWithoutPermit",
|
|
2757
|
+
inputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
|
|
2758
|
+
outputs: [
|
|
2759
|
+
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
2760
|
+
{ name: "error", type: "string", internalType: "string" },
|
|
2761
|
+
{ name: "decryptedValue", type: "uint256", internalType: "uint256" }
|
|
2762
|
+
],
|
|
2763
|
+
stateMutability: "view"
|
|
2764
|
+
}
|
|
2576
2765
|
];
|
|
2577
2766
|
|
|
2578
|
-
// core/decrypt/
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
await sleep(mocksSealOutputDelay);
|
|
2767
|
+
// core/decrypt/cofheMocksDecryptForView.ts
|
|
2768
|
+
async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient, mocksDecryptDelay) {
|
|
2769
|
+
if (mocksDecryptDelay > 0)
|
|
2770
|
+
await sleep(mocksDecryptDelay);
|
|
2583
2771
|
const permission = PermitUtils.getPermission(permit, true);
|
|
2584
2772
|
const permissionWithBigInts = {
|
|
2585
2773
|
...permission,
|
|
@@ -2587,19 +2775,19 @@ async function cofheMocksSealOutput(ctHash, utype, permit, publicClient, mocksSe
|
|
|
2587
2775
|
validatorId: BigInt(permission.validatorId)
|
|
2588
2776
|
};
|
|
2589
2777
|
const [allowed, error, result] = await publicClient.readContract({
|
|
2590
|
-
address:
|
|
2591
|
-
abi:
|
|
2778
|
+
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
2779
|
+
abi: MockThresholdNetworkAbi,
|
|
2592
2780
|
functionName: "querySealOutput",
|
|
2593
2781
|
args: [ctHash, BigInt(utype), permissionWithBigInts]
|
|
2594
2782
|
});
|
|
2595
2783
|
if (error != "") {
|
|
2596
|
-
throw new
|
|
2784
|
+
throw new CofheError({
|
|
2597
2785
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2598
2786
|
message: `mocks querySealOutput call failed: ${error}`
|
|
2599
2787
|
});
|
|
2600
2788
|
}
|
|
2601
2789
|
if (allowed == false) {
|
|
2602
|
-
throw new
|
|
2790
|
+
throw new CofheError({
|
|
2603
2791
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2604
2792
|
message: `mocks querySealOutput call failed: ACL Access Denied (NotAllowed)`
|
|
2605
2793
|
});
|
|
@@ -2618,7 +2806,7 @@ function numberArrayToUint8Array(arr) {
|
|
|
2618
2806
|
}
|
|
2619
2807
|
function convertSealedData(sealed) {
|
|
2620
2808
|
if (!sealed) {
|
|
2621
|
-
throw new
|
|
2809
|
+
throw new CofheError({
|
|
2622
2810
|
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2623
2811
|
message: "Sealed data is missing from completed response"
|
|
2624
2812
|
});
|
|
@@ -2645,7 +2833,7 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
2645
2833
|
body: JSON.stringify(body)
|
|
2646
2834
|
});
|
|
2647
2835
|
} catch (e) {
|
|
2648
|
-
throw new
|
|
2836
|
+
throw new CofheError({
|
|
2649
2837
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2650
2838
|
message: `sealOutput request failed`,
|
|
2651
2839
|
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
@@ -2664,7 +2852,7 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
2664
2852
|
} catch {
|
|
2665
2853
|
errorMessage = response.statusText || errorMessage;
|
|
2666
2854
|
}
|
|
2667
|
-
throw new
|
|
2855
|
+
throw new CofheError({
|
|
2668
2856
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2669
2857
|
message: `sealOutput request failed: ${errorMessage}`,
|
|
2670
2858
|
hint: "Check the threshold network URL and request parameters.",
|
|
@@ -2680,7 +2868,7 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
2680
2868
|
try {
|
|
2681
2869
|
submitResponse = await response.json();
|
|
2682
2870
|
} catch (e) {
|
|
2683
|
-
throw new
|
|
2871
|
+
throw new CofheError({
|
|
2684
2872
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2685
2873
|
message: `Failed to parse sealOutput submit response`,
|
|
2686
2874
|
cause: e instanceof Error ? e : void 0,
|
|
@@ -2691,7 +2879,7 @@ async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, per
|
|
|
2691
2879
|
});
|
|
2692
2880
|
}
|
|
2693
2881
|
if (!submitResponse.request_id) {
|
|
2694
|
-
throw new
|
|
2882
|
+
throw new CofheError({
|
|
2695
2883
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2696
2884
|
message: `sealOutput submit response missing request_id`,
|
|
2697
2885
|
context: {
|
|
@@ -2708,7 +2896,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2708
2896
|
let completed = false;
|
|
2709
2897
|
while (!completed) {
|
|
2710
2898
|
if (Date.now() - startTime > POLL_TIMEOUT_MS) {
|
|
2711
|
-
throw new
|
|
2899
|
+
throw new CofheError({
|
|
2712
2900
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2713
2901
|
message: `sealOutput polling timed out after ${POLL_TIMEOUT_MS}ms`,
|
|
2714
2902
|
hint: "The request may still be processing. Try again later.",
|
|
@@ -2728,7 +2916,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2728
2916
|
}
|
|
2729
2917
|
});
|
|
2730
2918
|
} catch (e) {
|
|
2731
|
-
throw new
|
|
2919
|
+
throw new CofheError({
|
|
2732
2920
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2733
2921
|
message: `sealOutput status poll failed`,
|
|
2734
2922
|
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
@@ -2740,7 +2928,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2740
2928
|
});
|
|
2741
2929
|
}
|
|
2742
2930
|
if (response.status === 404) {
|
|
2743
|
-
throw new
|
|
2931
|
+
throw new CofheError({
|
|
2744
2932
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2745
2933
|
message: `sealOutput request not found: ${requestId}`,
|
|
2746
2934
|
hint: "The request may have expired or been invalid.",
|
|
@@ -2758,7 +2946,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2758
2946
|
} catch {
|
|
2759
2947
|
errorMessage = response.statusText || errorMessage;
|
|
2760
2948
|
}
|
|
2761
|
-
throw new
|
|
2949
|
+
throw new CofheError({
|
|
2762
2950
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2763
2951
|
message: `sealOutput status poll failed: ${errorMessage}`,
|
|
2764
2952
|
context: {
|
|
@@ -2773,7 +2961,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2773
2961
|
try {
|
|
2774
2962
|
statusResponse = await response.json();
|
|
2775
2963
|
} catch (e) {
|
|
2776
|
-
throw new
|
|
2964
|
+
throw new CofheError({
|
|
2777
2965
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2778
2966
|
message: `Failed to parse sealOutput status response`,
|
|
2779
2967
|
cause: e instanceof Error ? e : void 0,
|
|
@@ -2786,7 +2974,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2786
2974
|
if (statusResponse.status === "COMPLETED") {
|
|
2787
2975
|
if (statusResponse.is_succeed === false) {
|
|
2788
2976
|
const errorMessage = statusResponse.error_message || "Unknown error";
|
|
2789
|
-
throw new
|
|
2977
|
+
throw new CofheError({
|
|
2790
2978
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2791
2979
|
message: `sealOutput request failed: ${errorMessage}`,
|
|
2792
2980
|
context: {
|
|
@@ -2797,7 +2985,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2797
2985
|
});
|
|
2798
2986
|
}
|
|
2799
2987
|
if (!statusResponse.sealed) {
|
|
2800
|
-
throw new
|
|
2988
|
+
throw new CofheError({
|
|
2801
2989
|
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2802
2990
|
message: `sealOutput request completed but returned no sealed data`,
|
|
2803
2991
|
context: {
|
|
@@ -2811,7 +2999,7 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2811
2999
|
}
|
|
2812
3000
|
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
2813
3001
|
}
|
|
2814
|
-
throw new
|
|
3002
|
+
throw new CofheError({
|
|
2815
3003
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2816
3004
|
message: "Polling loop exited unexpectedly",
|
|
2817
3005
|
context: {
|
|
@@ -2824,9 +3012,99 @@ async function tnSealOutputV2(ctHash, chainId, permission, thresholdNetworkUrl)
|
|
|
2824
3012
|
const requestId = await submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission);
|
|
2825
3013
|
return await pollSealOutputStatus(thresholdNetworkUrl, requestId);
|
|
2826
3014
|
}
|
|
3015
|
+
async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient, mocksDecryptForTxDelay) {
|
|
3016
|
+
if (mocksDecryptForTxDelay > 0)
|
|
3017
|
+
await sleep(mocksDecryptForTxDelay);
|
|
3018
|
+
if (permit !== null) {
|
|
3019
|
+
let permission = PermitUtils.getPermission(permit, true);
|
|
3020
|
+
const permissionWithBigInts = {
|
|
3021
|
+
...permission,
|
|
3022
|
+
expiration: BigInt(permission.expiration),
|
|
3023
|
+
validatorId: BigInt(permission.validatorId)
|
|
3024
|
+
};
|
|
3025
|
+
const [allowed2, error2, result2] = await publicClient.readContract({
|
|
3026
|
+
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
3027
|
+
abi: MockThresholdNetworkAbi,
|
|
3028
|
+
functionName: "decryptForTxWithPermit",
|
|
3029
|
+
args: [ctHash, permissionWithBigInts]
|
|
3030
|
+
});
|
|
3031
|
+
if (error2 != "") {
|
|
3032
|
+
throw new CofheError({
|
|
3033
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3034
|
+
message: `mocks decryptForTx call failed: ${error2}`
|
|
3035
|
+
});
|
|
3036
|
+
}
|
|
3037
|
+
if (allowed2 == false) {
|
|
3038
|
+
throw new CofheError({
|
|
3039
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3040
|
+
message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
|
|
3041
|
+
});
|
|
3042
|
+
}
|
|
3043
|
+
const chainId2 = await publicClient.getChainId();
|
|
3044
|
+
const ctHashBigInt2 = BigInt(ctHash);
|
|
3045
|
+
const resultBigInt2 = BigInt(result2);
|
|
3046
|
+
const encryptionType2 = Number((ctHashBigInt2 & 0x7fn << 8n) >> 8n);
|
|
3047
|
+
const ctHashBytes322 = viem.pad(viem.toHex(ctHashBigInt2), { size: 32 });
|
|
3048
|
+
const packed2 = viem.encodePacked(
|
|
3049
|
+
["uint256", "uint32", "uint64", "bytes32"],
|
|
3050
|
+
[resultBigInt2, encryptionType2, BigInt(chainId2), ctHashBytes322]
|
|
3051
|
+
);
|
|
3052
|
+
const messageHash2 = viem.keccak256(packed2);
|
|
3053
|
+
const signatureHex2 = await accounts.sign({
|
|
3054
|
+
hash: messageHash2,
|
|
3055
|
+
privateKey: MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY,
|
|
3056
|
+
to: "hex"
|
|
3057
|
+
});
|
|
3058
|
+
const signature2 = signatureHex2.slice(2);
|
|
3059
|
+
return {
|
|
3060
|
+
ctHash,
|
|
3061
|
+
decryptedValue: BigInt(result2),
|
|
3062
|
+
signature: signature2
|
|
3063
|
+
};
|
|
3064
|
+
}
|
|
3065
|
+
const [allowed, error, result] = await publicClient.readContract({
|
|
3066
|
+
address: MOCKS_THRESHOLD_NETWORK_ADDRESS,
|
|
3067
|
+
abi: MockThresholdNetworkAbi,
|
|
3068
|
+
functionName: "decryptForTxWithoutPermit",
|
|
3069
|
+
args: [ctHash]
|
|
3070
|
+
});
|
|
3071
|
+
if (error != "") {
|
|
3072
|
+
throw new CofheError({
|
|
3073
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3074
|
+
message: `mocks decryptForTx call failed: ${error}`
|
|
3075
|
+
});
|
|
3076
|
+
}
|
|
3077
|
+
if (allowed == false) {
|
|
3078
|
+
throw new CofheError({
|
|
3079
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3080
|
+
message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
|
|
3081
|
+
});
|
|
3082
|
+
}
|
|
3083
|
+
const chainId = await publicClient.getChainId();
|
|
3084
|
+
const ctHashBigInt = BigInt(ctHash);
|
|
3085
|
+
const resultBigInt = BigInt(result);
|
|
3086
|
+
const encryptionType = Number((ctHashBigInt & 0x7fn << 8n) >> 8n);
|
|
3087
|
+
const ctHashBytes32 = viem.pad(viem.toHex(ctHashBigInt), { size: 32 });
|
|
3088
|
+
const packed = viem.encodePacked(
|
|
3089
|
+
["uint256", "uint32", "uint64", "bytes32"],
|
|
3090
|
+
[resultBigInt, encryptionType, BigInt(chainId), ctHashBytes32]
|
|
3091
|
+
);
|
|
3092
|
+
const messageHash = viem.keccak256(packed);
|
|
3093
|
+
const signatureHex = await accounts.sign({
|
|
3094
|
+
hash: messageHash,
|
|
3095
|
+
privateKey: MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY,
|
|
3096
|
+
to: "hex"
|
|
3097
|
+
});
|
|
3098
|
+
const signature = signatureHex.slice(2);
|
|
3099
|
+
return {
|
|
3100
|
+
ctHash,
|
|
3101
|
+
decryptedValue: BigInt(result),
|
|
3102
|
+
signature
|
|
3103
|
+
};
|
|
3104
|
+
}
|
|
2827
3105
|
|
|
2828
|
-
// core/decrypt/
|
|
2829
|
-
var
|
|
3106
|
+
// core/decrypt/decryptForViewBuilder.ts
|
|
3107
|
+
var DecryptForViewBuilder = class extends BaseBuilder {
|
|
2830
3108
|
ctHash;
|
|
2831
3109
|
utype;
|
|
2832
3110
|
permitHash;
|
|
@@ -2852,12 +3130,12 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2852
3130
|
*
|
|
2853
3131
|
* Example:
|
|
2854
3132
|
* ```typescript
|
|
2855
|
-
* const unsealed = await
|
|
3133
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2856
3134
|
* .setChainId(11155111)
|
|
2857
|
-
* .
|
|
3135
|
+
* .execute();
|
|
2858
3136
|
* ```
|
|
2859
3137
|
*
|
|
2860
|
-
* @returns The chainable
|
|
3138
|
+
* @returns The chainable DecryptForViewBuilder instance.
|
|
2861
3139
|
*/
|
|
2862
3140
|
setChainId(chainId) {
|
|
2863
3141
|
this.chainId = chainId;
|
|
@@ -2873,12 +3151,12 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2873
3151
|
*
|
|
2874
3152
|
* Example:
|
|
2875
3153
|
* ```typescript
|
|
2876
|
-
* const unsealed = await
|
|
3154
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2877
3155
|
* .setAccount('0x1234567890123456789012345678901234567890')
|
|
2878
|
-
* .
|
|
3156
|
+
* .execute();
|
|
2879
3157
|
* ```
|
|
2880
3158
|
*
|
|
2881
|
-
* @returns The chainable
|
|
3159
|
+
* @returns The chainable DecryptForViewBuilder instance.
|
|
2882
3160
|
*/
|
|
2883
3161
|
setAccount(account) {
|
|
2884
3162
|
this.account = account;
|
|
@@ -2887,6 +3165,19 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2887
3165
|
getAccount() {
|
|
2888
3166
|
return this.account;
|
|
2889
3167
|
}
|
|
3168
|
+
withPermit(permitOrPermitHash) {
|
|
3169
|
+
if (typeof permitOrPermitHash === "string") {
|
|
3170
|
+
this.permitHash = permitOrPermitHash;
|
|
3171
|
+
this.permit = void 0;
|
|
3172
|
+
} else if (permitOrPermitHash === void 0) {
|
|
3173
|
+
this.permitHash = void 0;
|
|
3174
|
+
this.permit = void 0;
|
|
3175
|
+
} else {
|
|
3176
|
+
this.permit = permitOrPermitHash;
|
|
3177
|
+
this.permitHash = void 0;
|
|
3178
|
+
}
|
|
3179
|
+
return this;
|
|
3180
|
+
}
|
|
2890
3181
|
/**
|
|
2891
3182
|
* @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
|
|
2892
3183
|
*
|
|
@@ -2895,16 +3186,16 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2895
3186
|
*
|
|
2896
3187
|
* Example:
|
|
2897
3188
|
* ```typescript
|
|
2898
|
-
* const unsealed = await
|
|
3189
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2899
3190
|
* .setPermitHash('0x1234567890123456789012345678901234567890')
|
|
2900
|
-
* .
|
|
3191
|
+
* .execute();
|
|
2901
3192
|
* ```
|
|
2902
3193
|
*
|
|
2903
|
-
* @returns The chainable
|
|
3194
|
+
* @returns The chainable DecryptForViewBuilder instance.
|
|
2904
3195
|
*/
|
|
3196
|
+
/** @deprecated Use `withPermit(permitHash)` instead. */
|
|
2905
3197
|
setPermitHash(permitHash) {
|
|
2906
|
-
this.permitHash
|
|
2907
|
-
return this;
|
|
3198
|
+
return this.withPermit(permitHash);
|
|
2908
3199
|
}
|
|
2909
3200
|
getPermitHash() {
|
|
2910
3201
|
return this.permitHash;
|
|
@@ -2916,16 +3207,16 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2916
3207
|
*
|
|
2917
3208
|
* Example:
|
|
2918
3209
|
* ```typescript
|
|
2919
|
-
* const unsealed = await
|
|
3210
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
2920
3211
|
* .setPermit(permit)
|
|
2921
|
-
* .
|
|
3212
|
+
* .execute();
|
|
2922
3213
|
* ```
|
|
2923
3214
|
*
|
|
2924
|
-
* @returns The chainable
|
|
3215
|
+
* @returns The chainable DecryptForViewBuilder instance.
|
|
2925
3216
|
*/
|
|
3217
|
+
/** @deprecated Use `withPermit(permit)` instead. */
|
|
2926
3218
|
setPermit(permit) {
|
|
2927
|
-
this.permit
|
|
2928
|
-
return this;
|
|
3219
|
+
return this.withPermit(permit);
|
|
2929
3220
|
}
|
|
2930
3221
|
getPermit() {
|
|
2931
3222
|
return this.permit;
|
|
@@ -2936,7 +3227,7 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2936
3227
|
}
|
|
2937
3228
|
validateUtypeOrThrow() {
|
|
2938
3229
|
if (!isValidUtype(this.utype))
|
|
2939
|
-
throw new
|
|
3230
|
+
throw new CofheError({
|
|
2940
3231
|
code: "INVALID_UTYPE" /* InvalidUtype */,
|
|
2941
3232
|
message: `Invalid utype to decrypt to`,
|
|
2942
3233
|
context: {
|
|
@@ -2952,7 +3243,7 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2952
3243
|
if (this.permitHash) {
|
|
2953
3244
|
const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
|
|
2954
3245
|
if (!permit2) {
|
|
2955
|
-
throw new
|
|
3246
|
+
throw new CofheError({
|
|
2956
3247
|
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
2957
3248
|
message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
|
|
2958
3249
|
hint: "Ensure the permit exists and is valid.",
|
|
@@ -2967,7 +3258,7 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2967
3258
|
}
|
|
2968
3259
|
const permit = await permits.getActivePermit(this.chainId, this.account);
|
|
2969
3260
|
if (!permit) {
|
|
2970
|
-
throw new
|
|
3261
|
+
throw new CofheError({
|
|
2971
3262
|
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
2972
3263
|
message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
|
|
2973
3264
|
hint: "Ensure a permit exists for this account on this chain.",
|
|
@@ -2984,8 +3275,8 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
2984
3275
|
*/
|
|
2985
3276
|
async mocksSealOutput(permit) {
|
|
2986
3277
|
this.assertPublicClient();
|
|
2987
|
-
const
|
|
2988
|
-
return
|
|
3278
|
+
const mocksDecryptDelay = this.config.mocks.decryptDelay;
|
|
3279
|
+
return cofheMocksDecryptForView(this.ctHash, this.utype, permit, this.publicClient, mocksDecryptDelay);
|
|
2989
3280
|
}
|
|
2990
3281
|
/**
|
|
2991
3282
|
* In the production context, perform a true decryption with the CoFHE coprocessor.
|
|
@@ -3010,15 +3301,16 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
3010
3301
|
*
|
|
3011
3302
|
* Example:
|
|
3012
3303
|
* ```typescript
|
|
3013
|
-
* const unsealed = await
|
|
3304
|
+
* const unsealed = await client.decryptForView(ctHash, utype)
|
|
3014
3305
|
* .setChainId(11155111) // optional
|
|
3015
3306
|
* .setAccount('0x123...890') // optional
|
|
3016
|
-
* .
|
|
3307
|
+
* .withPermit() // optional
|
|
3308
|
+
* .execute(); // execute
|
|
3017
3309
|
* ```
|
|
3018
3310
|
*
|
|
3019
3311
|
* @returns The unsealed item.
|
|
3020
3312
|
*/
|
|
3021
|
-
async
|
|
3313
|
+
async execute() {
|
|
3022
3314
|
this.validateUtypeOrThrow();
|
|
3023
3315
|
const permit = await this.getResolvedPermit();
|
|
3024
3316
|
PermitUtils.validate(permit);
|
|
@@ -3034,6 +3326,394 @@ var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
|
3034
3326
|
}
|
|
3035
3327
|
};
|
|
3036
3328
|
|
|
3329
|
+
// core/decrypt/tnDecrypt.ts
|
|
3330
|
+
function normalizeSignature(signature) {
|
|
3331
|
+
if (typeof signature !== "string") {
|
|
3332
|
+
throw new CofheError({
|
|
3333
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3334
|
+
message: "decrypt response missing signature",
|
|
3335
|
+
context: {
|
|
3336
|
+
signature
|
|
3337
|
+
}
|
|
3338
|
+
});
|
|
3339
|
+
}
|
|
3340
|
+
const trimmed = signature.trim();
|
|
3341
|
+
if (trimmed.length === 0) {
|
|
3342
|
+
throw new CofheError({
|
|
3343
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3344
|
+
message: "decrypt response returned empty signature"
|
|
3345
|
+
});
|
|
3346
|
+
}
|
|
3347
|
+
return trimmed.startsWith("0x") ? trimmed.slice(2) : trimmed;
|
|
3348
|
+
}
|
|
3349
|
+
function parseDecryptedBytesToBigInt(decrypted) {
|
|
3350
|
+
if (!Array.isArray(decrypted)) {
|
|
3351
|
+
throw new CofheError({
|
|
3352
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3353
|
+
message: "decrypt response field <decrypted> must be a byte array",
|
|
3354
|
+
context: {
|
|
3355
|
+
decrypted
|
|
3356
|
+
}
|
|
3357
|
+
});
|
|
3358
|
+
}
|
|
3359
|
+
if (decrypted.length === 0) {
|
|
3360
|
+
throw new CofheError({
|
|
3361
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3362
|
+
message: "decrypt response field <decrypted> was an empty byte array",
|
|
3363
|
+
context: {
|
|
3364
|
+
decrypted
|
|
3365
|
+
}
|
|
3366
|
+
});
|
|
3367
|
+
}
|
|
3368
|
+
let hex = "";
|
|
3369
|
+
for (const b of decrypted) {
|
|
3370
|
+
if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
|
|
3371
|
+
throw new CofheError({
|
|
3372
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3373
|
+
message: "decrypt response field <decrypted> contained a non-byte value",
|
|
3374
|
+
context: {
|
|
3375
|
+
badElement: b,
|
|
3376
|
+
decrypted
|
|
3377
|
+
}
|
|
3378
|
+
});
|
|
3379
|
+
}
|
|
3380
|
+
hex += b.toString(16).padStart(2, "0");
|
|
3381
|
+
}
|
|
3382
|
+
return BigInt(`0x${hex}`);
|
|
3383
|
+
}
|
|
3384
|
+
function assertTnDecryptResponse(value) {
|
|
3385
|
+
if (value == null || typeof value !== "object") {
|
|
3386
|
+
throw new CofheError({
|
|
3387
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3388
|
+
message: "decrypt response must be a JSON object",
|
|
3389
|
+
context: {
|
|
3390
|
+
value
|
|
3391
|
+
}
|
|
3392
|
+
});
|
|
3393
|
+
}
|
|
3394
|
+
const v = value;
|
|
3395
|
+
const decrypted = v.decrypted;
|
|
3396
|
+
const signature = v.signature;
|
|
3397
|
+
const encryptionType = v.encryption_type;
|
|
3398
|
+
const errorMessage = v.error_message;
|
|
3399
|
+
if (!Array.isArray(decrypted)) {
|
|
3400
|
+
throw new CofheError({
|
|
3401
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3402
|
+
message: "decrypt response missing <decrypted> byte array",
|
|
3403
|
+
context: { decryptResponse: value }
|
|
3404
|
+
});
|
|
3405
|
+
}
|
|
3406
|
+
if (typeof signature !== "string") {
|
|
3407
|
+
throw new CofheError({
|
|
3408
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3409
|
+
message: "decrypt response missing <signature> string",
|
|
3410
|
+
context: { decryptResponse: value }
|
|
3411
|
+
});
|
|
3412
|
+
}
|
|
3413
|
+
if (typeof encryptionType !== "number") {
|
|
3414
|
+
throw new CofheError({
|
|
3415
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3416
|
+
message: "decrypt response missing <encryption_type> number",
|
|
3417
|
+
context: { decryptResponse: value }
|
|
3418
|
+
});
|
|
3419
|
+
}
|
|
3420
|
+
if (!(typeof errorMessage === "string" || errorMessage === null)) {
|
|
3421
|
+
throw new CofheError({
|
|
3422
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3423
|
+
message: "decrypt response field <error_message> must be string or null",
|
|
3424
|
+
context: { decryptResponse: value }
|
|
3425
|
+
});
|
|
3426
|
+
}
|
|
3427
|
+
return {
|
|
3428
|
+
decrypted,
|
|
3429
|
+
signature,
|
|
3430
|
+
encryption_type: encryptionType,
|
|
3431
|
+
error_message: errorMessage
|
|
3432
|
+
};
|
|
3433
|
+
}
|
|
3434
|
+
async function tnDecrypt(ctHash, chainId, permission, thresholdNetworkUrl) {
|
|
3435
|
+
const body = {
|
|
3436
|
+
ct_tempkey: ctHash.toString(16).padStart(64, "0"),
|
|
3437
|
+
host_chain_id: chainId
|
|
3438
|
+
};
|
|
3439
|
+
if (permission) {
|
|
3440
|
+
body.permit = permission;
|
|
3441
|
+
}
|
|
3442
|
+
let response;
|
|
3443
|
+
try {
|
|
3444
|
+
response = await fetch(`${thresholdNetworkUrl}/decrypt`, {
|
|
3445
|
+
method: "POST",
|
|
3446
|
+
headers: {
|
|
3447
|
+
"Content-Type": "application/json"
|
|
3448
|
+
},
|
|
3449
|
+
body: JSON.stringify(body)
|
|
3450
|
+
});
|
|
3451
|
+
} catch (e) {
|
|
3452
|
+
throw new CofheError({
|
|
3453
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3454
|
+
message: `decrypt request failed`,
|
|
3455
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3456
|
+
cause: e instanceof Error ? e : void 0,
|
|
3457
|
+
context: {
|
|
3458
|
+
thresholdNetworkUrl,
|
|
3459
|
+
body
|
|
3460
|
+
}
|
|
3461
|
+
});
|
|
3462
|
+
}
|
|
3463
|
+
const responseText = await response.text();
|
|
3464
|
+
if (!response.ok) {
|
|
3465
|
+
let errorMessage = response.statusText || `HTTP ${response.status}`;
|
|
3466
|
+
try {
|
|
3467
|
+
const errorBody = JSON.parse(responseText);
|
|
3468
|
+
const maybeMessage = errorBody.error_message || errorBody.message;
|
|
3469
|
+
if (typeof maybeMessage === "string" && maybeMessage.length > 0)
|
|
3470
|
+
errorMessage = maybeMessage;
|
|
3471
|
+
} catch {
|
|
3472
|
+
const trimmed = responseText.trim();
|
|
3473
|
+
if (trimmed.length > 0)
|
|
3474
|
+
errorMessage = trimmed;
|
|
3475
|
+
}
|
|
3476
|
+
throw new CofheError({
|
|
3477
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3478
|
+
message: `decrypt request failed: ${errorMessage}`,
|
|
3479
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
3480
|
+
context: {
|
|
3481
|
+
thresholdNetworkUrl,
|
|
3482
|
+
status: response.status,
|
|
3483
|
+
statusText: response.statusText,
|
|
3484
|
+
body,
|
|
3485
|
+
responseText
|
|
3486
|
+
}
|
|
3487
|
+
});
|
|
3488
|
+
}
|
|
3489
|
+
let rawJson;
|
|
3490
|
+
try {
|
|
3491
|
+
rawJson = JSON.parse(responseText);
|
|
3492
|
+
} catch (e) {
|
|
3493
|
+
throw new CofheError({
|
|
3494
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3495
|
+
message: `Failed to parse decrypt response`,
|
|
3496
|
+
cause: e instanceof Error ? e : void 0,
|
|
3497
|
+
context: {
|
|
3498
|
+
thresholdNetworkUrl,
|
|
3499
|
+
body,
|
|
3500
|
+
responseText
|
|
3501
|
+
}
|
|
3502
|
+
});
|
|
3503
|
+
}
|
|
3504
|
+
const decryptResponse = assertTnDecryptResponse(rawJson);
|
|
3505
|
+
if (decryptResponse.error_message) {
|
|
3506
|
+
throw new CofheError({
|
|
3507
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3508
|
+
message: `decrypt request failed: ${decryptResponse.error_message}`,
|
|
3509
|
+
context: {
|
|
3510
|
+
thresholdNetworkUrl,
|
|
3511
|
+
body,
|
|
3512
|
+
decryptResponse
|
|
3513
|
+
}
|
|
3514
|
+
});
|
|
3515
|
+
}
|
|
3516
|
+
const decryptedValue = parseDecryptedBytesToBigInt(decryptResponse.decrypted);
|
|
3517
|
+
const signature = normalizeSignature(decryptResponse.signature);
|
|
3518
|
+
return { decryptedValue, signature };
|
|
3519
|
+
}
|
|
3520
|
+
|
|
3521
|
+
// core/decrypt/decryptForTxBuilder.ts
|
|
3522
|
+
var DecryptForTxBuilder = class extends BaseBuilder {
|
|
3523
|
+
ctHash;
|
|
3524
|
+
permitHash;
|
|
3525
|
+
permit;
|
|
3526
|
+
permitSelection = "unset";
|
|
3527
|
+
constructor(params) {
|
|
3528
|
+
super({
|
|
3529
|
+
config: params.config,
|
|
3530
|
+
publicClient: params.publicClient,
|
|
3531
|
+
walletClient: params.walletClient,
|
|
3532
|
+
chainId: params.chainId,
|
|
3533
|
+
account: params.account,
|
|
3534
|
+
requireConnected: params.requireConnected
|
|
3535
|
+
});
|
|
3536
|
+
this.ctHash = params.ctHash;
|
|
3537
|
+
}
|
|
3538
|
+
setChainId(chainId) {
|
|
3539
|
+
this.chainId = chainId;
|
|
3540
|
+
return this;
|
|
3541
|
+
}
|
|
3542
|
+
getChainId() {
|
|
3543
|
+
return this.chainId;
|
|
3544
|
+
}
|
|
3545
|
+
setAccount(account) {
|
|
3546
|
+
this.account = account;
|
|
3547
|
+
return this;
|
|
3548
|
+
}
|
|
3549
|
+
getAccount() {
|
|
3550
|
+
return this.account;
|
|
3551
|
+
}
|
|
3552
|
+
withPermit(permitOrPermitHash) {
|
|
3553
|
+
if (this.permitSelection === "with-permit") {
|
|
3554
|
+
throw new CofheError({
|
|
3555
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3556
|
+
message: "decryptForTx: withPermit() can only be selected once.",
|
|
3557
|
+
hint: "Choose the permit mode once. If you need a different permit, start a new decryptForTx() builder chain."
|
|
3558
|
+
});
|
|
3559
|
+
}
|
|
3560
|
+
if (this.permitSelection === "without-permit") {
|
|
3561
|
+
throw new CofheError({
|
|
3562
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3563
|
+
message: "decryptForTx: cannot call withPermit() after withoutPermit() has been selected.",
|
|
3564
|
+
hint: "Choose exactly one permit mode: either call .withPermit(...) or .withoutPermit(), but not both."
|
|
3565
|
+
});
|
|
3566
|
+
}
|
|
3567
|
+
this.permitSelection = "with-permit";
|
|
3568
|
+
if (typeof permitOrPermitHash === "string") {
|
|
3569
|
+
this.permitHash = permitOrPermitHash;
|
|
3570
|
+
this.permit = void 0;
|
|
3571
|
+
} else if (permitOrPermitHash === void 0) {
|
|
3572
|
+
this.permitHash = void 0;
|
|
3573
|
+
this.permit = void 0;
|
|
3574
|
+
} else {
|
|
3575
|
+
this.permit = permitOrPermitHash;
|
|
3576
|
+
this.permitHash = void 0;
|
|
3577
|
+
}
|
|
3578
|
+
return this;
|
|
3579
|
+
}
|
|
3580
|
+
/**
|
|
3581
|
+
* Select "no permit" mode.
|
|
3582
|
+
*
|
|
3583
|
+
* This uses global allowance (no permit required) and sends an empty permission payload to `/decrypt`.
|
|
3584
|
+
*/
|
|
3585
|
+
withoutPermit() {
|
|
3586
|
+
if (this.permitSelection === "without-permit") {
|
|
3587
|
+
throw new CofheError({
|
|
3588
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3589
|
+
message: "decryptForTx: withoutPermit() can only be selected once.",
|
|
3590
|
+
hint: "Choose the permit mode once. If you need a different mode, start a new decryptForTx() builder chain."
|
|
3591
|
+
});
|
|
3592
|
+
}
|
|
3593
|
+
if (this.permitSelection === "with-permit") {
|
|
3594
|
+
throw new CofheError({
|
|
3595
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3596
|
+
message: "decryptForTx: cannot call withoutPermit() after withPermit() has been selected.",
|
|
3597
|
+
hint: "Choose exactly one permit mode: either call .withPermit(...) or .withoutPermit(), but not both."
|
|
3598
|
+
});
|
|
3599
|
+
}
|
|
3600
|
+
this.permitSelection = "without-permit";
|
|
3601
|
+
this.permitHash = void 0;
|
|
3602
|
+
this.permit = void 0;
|
|
3603
|
+
return this;
|
|
3604
|
+
}
|
|
3605
|
+
getPermit() {
|
|
3606
|
+
return this.permit;
|
|
3607
|
+
}
|
|
3608
|
+
getPermitHash() {
|
|
3609
|
+
return this.permitHash;
|
|
3610
|
+
}
|
|
3611
|
+
async getThresholdNetworkUrl() {
|
|
3612
|
+
this.assertChainId();
|
|
3613
|
+
return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
|
|
3614
|
+
}
|
|
3615
|
+
async getResolvedPermit() {
|
|
3616
|
+
if (this.permitSelection === "unset") {
|
|
3617
|
+
throw new CofheError({
|
|
3618
|
+
code: "INTERNAL_ERROR" /* InternalError */,
|
|
3619
|
+
message: "decryptForTx: missing permit selection; call withPermit(...) or withoutPermit() before execute().",
|
|
3620
|
+
hint: "Call .withPermit() to use the active permit, or .withoutPermit() for global allowance."
|
|
3621
|
+
});
|
|
3622
|
+
}
|
|
3623
|
+
if (this.permitSelection === "without-permit") {
|
|
3624
|
+
return null;
|
|
3625
|
+
}
|
|
3626
|
+
if (this.permit)
|
|
3627
|
+
return this.permit;
|
|
3628
|
+
this.assertChainId();
|
|
3629
|
+
this.assertAccount();
|
|
3630
|
+
if (this.permitHash) {
|
|
3631
|
+
const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
|
|
3632
|
+
if (!permit2) {
|
|
3633
|
+
throw new CofheError({
|
|
3634
|
+
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
3635
|
+
message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
|
|
3636
|
+
hint: "Ensure the permit exists and is valid.",
|
|
3637
|
+
context: {
|
|
3638
|
+
chainId: this.chainId,
|
|
3639
|
+
account: this.account,
|
|
3640
|
+
permitHash: this.permitHash
|
|
3641
|
+
}
|
|
3642
|
+
});
|
|
3643
|
+
}
|
|
3644
|
+
return permit2;
|
|
3645
|
+
}
|
|
3646
|
+
const permit = await permits.getActivePermit(this.chainId, this.account);
|
|
3647
|
+
if (!permit) {
|
|
3648
|
+
throw new CofheError({
|
|
3649
|
+
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
3650
|
+
message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
|
|
3651
|
+
hint: "Create a permit (e.g. client.permits.createSelf(...)) and/or set it active (client.permits.selectActivePermit(hash)).",
|
|
3652
|
+
context: {
|
|
3653
|
+
chainId: this.chainId,
|
|
3654
|
+
account: this.account
|
|
3655
|
+
}
|
|
3656
|
+
});
|
|
3657
|
+
}
|
|
3658
|
+
return permit;
|
|
3659
|
+
}
|
|
3660
|
+
/**
|
|
3661
|
+
* On hardhat, interact with MockThresholdNetwork contract
|
|
3662
|
+
*/
|
|
3663
|
+
async mocksDecryptForTx(permit) {
|
|
3664
|
+
this.assertPublicClient();
|
|
3665
|
+
const delay = this.config.mocks.decryptDelay;
|
|
3666
|
+
const result = await cofheMocksDecryptForTx(this.ctHash, 0, permit, this.publicClient, delay);
|
|
3667
|
+
return result;
|
|
3668
|
+
}
|
|
3669
|
+
/**
|
|
3670
|
+
* In the production context, perform a true decryption with the CoFHE coprocessor.
|
|
3671
|
+
*/
|
|
3672
|
+
async productionDecryptForTx(permit) {
|
|
3673
|
+
this.assertChainId();
|
|
3674
|
+
this.assertPublicClient();
|
|
3675
|
+
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3676
|
+
const permission = permit ? PermitUtils.getPermission(permit, true) : null;
|
|
3677
|
+
const { decryptedValue, signature } = await tnDecrypt(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
|
|
3678
|
+
return {
|
|
3679
|
+
ctHash: this.ctHash,
|
|
3680
|
+
decryptedValue,
|
|
3681
|
+
signature
|
|
3682
|
+
};
|
|
3683
|
+
}
|
|
3684
|
+
/**
|
|
3685
|
+
* Final step of the decryptForTx process. MUST BE CALLED LAST IN THE CHAIN.
|
|
3686
|
+
*
|
|
3687
|
+
* You must explicitly choose one permit mode before calling `execute()`:
|
|
3688
|
+
* - `withPermit(permit)` / `withPermit(permitHash)` / `withPermit()` (active permit)
|
|
3689
|
+
* - `withoutPermit()` (global allowance)
|
|
3690
|
+
*/
|
|
3691
|
+
async execute() {
|
|
3692
|
+
const permit = await this.getResolvedPermit();
|
|
3693
|
+
if (permit !== null) {
|
|
3694
|
+
PermitUtils.validate(permit);
|
|
3695
|
+
PermitUtils.isValid(permit);
|
|
3696
|
+
const chainId = permit._signedDomain.chainId;
|
|
3697
|
+
if (chainId === hardhat2.id) {
|
|
3698
|
+
return await this.mocksDecryptForTx(permit);
|
|
3699
|
+
} else {
|
|
3700
|
+
return await this.productionDecryptForTx(permit);
|
|
3701
|
+
}
|
|
3702
|
+
} else {
|
|
3703
|
+
if (!this.chainId) {
|
|
3704
|
+
this.assertPublicClient();
|
|
3705
|
+
this.chainId = await getPublicClientChainID(this.publicClient);
|
|
3706
|
+
}
|
|
3707
|
+
this.assertChainId();
|
|
3708
|
+
if (this.chainId === hardhat2.id) {
|
|
3709
|
+
return await this.mocksDecryptForTx(null);
|
|
3710
|
+
} else {
|
|
3711
|
+
return await this.productionDecryptForTx(null);
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
}
|
|
3715
|
+
};
|
|
3716
|
+
|
|
3037
3717
|
// core/client.ts
|
|
3038
3718
|
var InitialConnectStore = {
|
|
3039
3719
|
connected: false,
|
|
@@ -3044,9 +3724,10 @@ var InitialConnectStore = {
|
|
|
3044
3724
|
publicClient: void 0,
|
|
3045
3725
|
walletClient: void 0
|
|
3046
3726
|
};
|
|
3047
|
-
function
|
|
3727
|
+
function createCofheClientBase(opts) {
|
|
3048
3728
|
const keysStorage = createKeysStore(opts.config.fheKeyStorage);
|
|
3049
3729
|
const connectStore = vanilla.createStore(() => InitialConnectStore);
|
|
3730
|
+
let connectAttemptId = 0;
|
|
3050
3731
|
const updateConnectState = (partial) => {
|
|
3051
3732
|
connectStore.setState((state) => ({ ...state, ...partial }));
|
|
3052
3733
|
};
|
|
@@ -3054,7 +3735,7 @@ function createCofhesdkClientBase(opts) {
|
|
|
3054
3735
|
const state = connectStore.getState();
|
|
3055
3736
|
const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
|
|
3056
3737
|
if (notConnected) {
|
|
3057
|
-
throw new
|
|
3738
|
+
throw new CofheError({
|
|
3058
3739
|
code: "NOT_CONNECTED" /* NotConnected */,
|
|
3059
3740
|
message: "Client must be connected, account and chainId must be initialized",
|
|
3060
3741
|
hint: "Ensure client.connect() has been called and awaited.",
|
|
@@ -3072,6 +3753,8 @@ function createCofhesdkClientBase(opts) {
|
|
|
3072
3753
|
const state = connectStore.getState();
|
|
3073
3754
|
if (state.connected && state.publicClient === publicClient && state.walletClient === walletClient)
|
|
3074
3755
|
return;
|
|
3756
|
+
connectAttemptId += 1;
|
|
3757
|
+
const localAttemptId = connectAttemptId;
|
|
3075
3758
|
updateConnectState({
|
|
3076
3759
|
...InitialConnectStore,
|
|
3077
3760
|
connecting: true
|
|
@@ -3079,6 +3762,8 @@ function createCofhesdkClientBase(opts) {
|
|
|
3079
3762
|
try {
|
|
3080
3763
|
const chainId = await getPublicClientChainID(publicClient);
|
|
3081
3764
|
const account = await getWalletClientAccount(walletClient);
|
|
3765
|
+
if (localAttemptId !== connectAttemptId)
|
|
3766
|
+
return;
|
|
3082
3767
|
updateConnectState({
|
|
3083
3768
|
connected: true,
|
|
3084
3769
|
connecting: false,
|
|
@@ -3089,6 +3774,8 @@ function createCofhesdkClientBase(opts) {
|
|
|
3089
3774
|
walletClient
|
|
3090
3775
|
});
|
|
3091
3776
|
} catch (e) {
|
|
3777
|
+
if (localAttemptId !== connectAttemptId)
|
|
3778
|
+
return;
|
|
3092
3779
|
updateConnectState({
|
|
3093
3780
|
...InitialConnectStore,
|
|
3094
3781
|
connectError: e
|
|
@@ -3096,6 +3783,10 @@ function createCofhesdkClientBase(opts) {
|
|
|
3096
3783
|
throw e;
|
|
3097
3784
|
}
|
|
3098
3785
|
}
|
|
3786
|
+
function disconnect() {
|
|
3787
|
+
connectAttemptId += 1;
|
|
3788
|
+
updateConnectState({ ...InitialConnectStore });
|
|
3789
|
+
}
|
|
3099
3790
|
function encryptInputs(inputs) {
|
|
3100
3791
|
const state = connectStore.getState();
|
|
3101
3792
|
return new EncryptInputsBuilder({
|
|
@@ -3115,16 +3806,28 @@ function createCofhesdkClientBase(opts) {
|
|
|
3115
3806
|
requireConnected: _requireConnected
|
|
3116
3807
|
});
|
|
3117
3808
|
}
|
|
3118
|
-
function
|
|
3809
|
+
function decryptForView(ctHash, utype) {
|
|
3119
3810
|
const state = connectStore.getState();
|
|
3120
|
-
return new
|
|
3811
|
+
return new DecryptForViewBuilder({
|
|
3121
3812
|
ctHash,
|
|
3122
3813
|
utype,
|
|
3123
|
-
chainId: state.chainId
|
|
3124
|
-
account: state.account
|
|
3814
|
+
chainId: state.chainId,
|
|
3815
|
+
account: state.account,
|
|
3125
3816
|
config: opts.config,
|
|
3126
|
-
publicClient: state.publicClient
|
|
3127
|
-
walletClient: state.walletClient
|
|
3817
|
+
publicClient: state.publicClient,
|
|
3818
|
+
walletClient: state.walletClient,
|
|
3819
|
+
requireConnected: _requireConnected
|
|
3820
|
+
});
|
|
3821
|
+
}
|
|
3822
|
+
function decryptForTx(ctHash) {
|
|
3823
|
+
const state = connectStore.getState();
|
|
3824
|
+
return new DecryptForTxBuilder({
|
|
3825
|
+
ctHash,
|
|
3826
|
+
chainId: state.chainId,
|
|
3827
|
+
account: state.account,
|
|
3828
|
+
config: opts.config,
|
|
3829
|
+
publicClient: state.publicClient,
|
|
3830
|
+
walletClient: state.walletClient,
|
|
3128
3831
|
requireConnected: _requireConnected
|
|
3129
3832
|
});
|
|
3130
3833
|
}
|
|
@@ -3133,7 +3836,7 @@ function createCofhesdkClientBase(opts) {
|
|
|
3133
3836
|
const _chainId = chainId ?? state.chainId;
|
|
3134
3837
|
const _account = account ?? state.account;
|
|
3135
3838
|
if (_chainId == null || _account == null) {
|
|
3136
|
-
throw new
|
|
3839
|
+
throw new CofheError({
|
|
3137
3840
|
code: "NOT_CONNECTED" /* NotConnected */,
|
|
3138
3841
|
message: "ChainId or account not available.",
|
|
3139
3842
|
hint: "Ensure client.connect() has been called, or provide chainId and account explicitly.",
|
|
@@ -3200,9 +3903,9 @@ function createCofhesdkClientBase(opts) {
|
|
|
3200
3903
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
3201
3904
|
return permits.selectActivePermit(_chainId, _account, hash);
|
|
3202
3905
|
},
|
|
3203
|
-
removePermit: async (hash, chainId, account
|
|
3906
|
+
removePermit: async (hash, chainId, account) => {
|
|
3204
3907
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
3205
|
-
return permits.removePermit(_chainId, _account, hash
|
|
3908
|
+
return permits.removePermit(_chainId, _account, hash);
|
|
3206
3909
|
},
|
|
3207
3910
|
removeActivePermit: async (chainId, account) => {
|
|
3208
3911
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
@@ -3218,6 +3921,9 @@ function createCofhesdkClientBase(opts) {
|
|
|
3218
3921
|
getSnapshot: connectStore.getState,
|
|
3219
3922
|
subscribe: connectStore.subscribe,
|
|
3220
3923
|
// flags (read-only: reflect snapshot)
|
|
3924
|
+
get connection() {
|
|
3925
|
+
return connectStore.getState();
|
|
3926
|
+
},
|
|
3221
3927
|
get connected() {
|
|
3222
3928
|
return connectStore.getState().connected;
|
|
3223
3929
|
},
|
|
@@ -3227,8 +3933,14 @@ function createCofhesdkClientBase(opts) {
|
|
|
3227
3933
|
// config & platform-specific (read-only)
|
|
3228
3934
|
config: opts.config,
|
|
3229
3935
|
connect,
|
|
3936
|
+
disconnect,
|
|
3230
3937
|
encryptInputs,
|
|
3231
|
-
|
|
3938
|
+
decryptForView,
|
|
3939
|
+
/**
|
|
3940
|
+
* @deprecated Use `decryptForView` instead. Kept for backward compatibility.
|
|
3941
|
+
*/
|
|
3942
|
+
decryptHandle: decryptForView,
|
|
3943
|
+
decryptForTx,
|
|
3232
3944
|
permits: clientPermits
|
|
3233
3945
|
// Add SDK-specific methods below that require connection
|
|
3234
3946
|
// Example:
|
|
@@ -3441,15 +4153,15 @@ async function zkProveWithWorker2(fheKeyHex, crsHex, items, metadata) {
|
|
|
3441
4153
|
const workerManager2 = getWorkerManager();
|
|
3442
4154
|
return await workerManager2.submitProof(fheKeyHex, crsHex, serializedItems, metadata);
|
|
3443
4155
|
}
|
|
3444
|
-
function
|
|
3445
|
-
return
|
|
4156
|
+
function createCofheConfig(config) {
|
|
4157
|
+
return createCofheConfigBase({
|
|
3446
4158
|
environment: "web",
|
|
3447
4159
|
...config,
|
|
3448
4160
|
fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? createWebStorage()
|
|
3449
4161
|
});
|
|
3450
4162
|
}
|
|
3451
|
-
function
|
|
3452
|
-
return
|
|
4163
|
+
function createCofheClient(config) {
|
|
4164
|
+
return createCofheClientBase({
|
|
3453
4165
|
config,
|
|
3454
4166
|
zkBuilderAndCrsGenerator,
|
|
3455
4167
|
tfhePublicKeyDeserializer,
|
|
@@ -3460,8 +4172,8 @@ function createCofhesdkClient(config) {
|
|
|
3460
4172
|
zkProveWorkerFn: areWorkersAvailable() ? zkProveWithWorker2 : void 0
|
|
3461
4173
|
});
|
|
3462
4174
|
}
|
|
3463
|
-
function
|
|
3464
|
-
return
|
|
4175
|
+
function createCofheClientWithCustomWorker(config, customZkProveWorkerFn) {
|
|
4176
|
+
return createCofheClientBase({
|
|
3465
4177
|
config,
|
|
3466
4178
|
zkBuilderAndCrsGenerator,
|
|
3467
4179
|
tfhePublicKeyDeserializer,
|
|
@@ -3472,7 +4184,7 @@ function createCofhesdkClientWithCustomWorker(config, customZkProveWorkerFn) {
|
|
|
3472
4184
|
}
|
|
3473
4185
|
|
|
3474
4186
|
exports.areWorkersAvailable = areWorkersAvailable;
|
|
3475
|
-
exports.
|
|
3476
|
-
exports.
|
|
3477
|
-
exports.
|
|
4187
|
+
exports.createCofheClient = createCofheClient;
|
|
4188
|
+
exports.createCofheClientWithCustomWorker = createCofheClientWithCustomWorker;
|
|
4189
|
+
exports.createCofheConfig = createCofheConfig;
|
|
3478
4190
|
exports.terminateWorker = terminateWorker;
|