@cofhe/sdk 0.1.1 → 0.2.1
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 +22 -0
- package/adapters/ethers6.ts +28 -28
- package/adapters/hardhat.ts +0 -1
- package/adapters/index.test.ts +14 -19
- package/adapters/smartWallet.ts +81 -73
- package/adapters/test-utils.ts +45 -45
- package/adapters/types.ts +3 -3
- package/chains/chains/localcofhe.ts +14 -0
- package/chains/chains.test.ts +2 -1
- package/chains/defineChain.ts +2 -2
- package/chains/index.ts +3 -1
- package/chains/types.ts +3 -3
- package/core/baseBuilder.ts +30 -49
- package/core/client.test.ts +200 -72
- package/core/client.ts +152 -148
- package/core/clientTypes.ts +114 -0
- package/core/config.test.ts +30 -11
- package/core/config.ts +26 -13
- package/core/consts.ts +18 -0
- package/core/decrypt/cofheMocksSealOutput.ts +2 -4
- package/core/decrypt/decryptHandleBuilder.ts +51 -45
- package/core/decrypt/{tnSealOutput.ts → tnSealOutputV1.ts} +1 -1
- package/core/decrypt/tnSealOutputV2.ts +298 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +15 -16
- package/core/encrypt/encryptInputsBuilder.test.ts +132 -116
- package/core/encrypt/encryptInputsBuilder.ts +159 -111
- package/core/encrypt/encryptUtils.ts +6 -3
- package/core/encrypt/zkPackProveVerify.ts +70 -8
- package/core/error.ts +0 -2
- package/core/fetchKeys.test.ts +1 -18
- package/core/fetchKeys.ts +0 -26
- package/core/index.ts +37 -17
- package/core/keyStore.ts +65 -38
- package/core/permits.test.ts +255 -4
- package/core/permits.ts +83 -18
- package/core/types.ts +198 -152
- package/core/utils.ts +43 -1
- package/dist/adapters.d.cts +38 -20
- package/dist/adapters.d.ts +38 -20
- package/dist/chains.cjs +18 -8
- package/dist/chains.d.cts +31 -9
- package/dist/chains.d.ts +31 -9
- package/dist/chains.js +1 -1
- package/dist/{chunk-KFGPTJ6X.js → chunk-I5WFEYXX.js} +1768 -1526
- package/dist/{chunk-LU7BMUUT.js → chunk-R3B5TMVX.js} +330 -197
- package/dist/{chunk-GZCQQYVI.js → chunk-TBLR7NNE.js} +18 -9
- package/dist/{types-PhwGgQvs.d.ts → clientTypes-RqkgkV2i.d.ts} +331 -429
- package/dist/{types-bB7wLj0q.d.cts → clientTypes-e4filDzK.d.cts} +331 -429
- package/dist/core.cjs +3000 -2625
- package/dist/core.d.cts +113 -7
- package/dist/core.d.ts +113 -7
- package/dist/core.js +3 -3
- package/dist/node.cjs +2851 -2526
- package/dist/node.d.cts +4 -4
- package/dist/node.d.ts +4 -4
- package/dist/node.js +4 -3
- package/dist/{permit-S9CnI6MF.d.cts → permit-MZ502UBl.d.cts} +54 -41
- package/dist/{permit-S9CnI6MF.d.ts → permit-MZ502UBl.d.ts} +54 -41
- package/dist/permits.cjs +328 -195
- package/dist/permits.d.cts +113 -825
- package/dist/permits.d.ts +113 -825
- 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 +3067 -2527
- package/dist/web.d.cts +22 -6
- package/dist/web.d.ts +22 -6
- package/dist/web.js +185 -9
- package/dist/zkProve.worker.cjs +93 -0
- package/dist/zkProve.worker.d.cts +2 -0
- package/dist/zkProve.worker.d.ts +2 -0
- package/dist/zkProve.worker.js +91 -0
- package/node/client.test.ts +20 -25
- package/node/encryptInputs.test.ts +18 -38
- package/node/index.ts +1 -0
- package/package.json +15 -15
- package/permits/index.ts +1 -0
- package/permits/localstorage.test.ts +9 -14
- package/permits/onchain-utils.ts +221 -0
- package/permits/permit.test.ts +76 -27
- package/permits/permit.ts +58 -95
- package/permits/sealing.test.ts +3 -3
- package/permits/sealing.ts +2 -2
- package/permits/store.test.ts +10 -50
- package/permits/store.ts +9 -21
- package/permits/test-utils.ts +11 -3
- package/permits/types.ts +39 -9
- package/permits/utils.ts +0 -5
- package/permits/validation.test.ts +29 -32
- package/permits/validation.ts +114 -176
- package/web/client.web.test.ts +20 -25
- package/web/config.web.test.ts +0 -2
- package/web/encryptInputs.web.test.ts +31 -54
- package/web/index.ts +65 -1
- package/web/storage.ts +19 -5
- package/web/worker.builder.web.test.ts +148 -0
- package/web/worker.config.web.test.ts +329 -0
- package/web/worker.output.web.test.ts +84 -0
- package/web/workerManager.test.ts +80 -0
- package/web/workerManager.ts +214 -0
- package/web/workerManager.web.test.ts +114 -0
- package/web/zkProve.worker.ts +133 -0
- package/core/result.test.ts +0 -180
- package/core/result.ts +0 -67
- package/core/test-utils.ts +0 -45
- package/dist/types-KImPrEIe.d.cts +0 -48
- package/dist/types-KImPrEIe.d.ts +0 -48
package/permits/validation.ts
CHANGED
|
@@ -1,42 +1,48 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { isAddress, zeroAddress } from 'viem';
|
|
3
|
-
import {
|
|
4
|
-
import { is0xPrefixed } from './utils.js';
|
|
2
|
+
import { getAddress, isAddress, isHex, zeroAddress, type Hex } from 'viem';
|
|
3
|
+
import type { Permit, ValidationResult } from './types.js';
|
|
5
4
|
|
|
6
5
|
const SerializedSealingPair = z.object({
|
|
7
6
|
privateKey: z.string(),
|
|
8
7
|
publicKey: z.string(),
|
|
9
8
|
});
|
|
10
9
|
|
|
10
|
+
export const addressSchema = z
|
|
11
|
+
.string()
|
|
12
|
+
.refine((val) => isAddress(val), {
|
|
13
|
+
error: 'Invalid address',
|
|
14
|
+
})
|
|
15
|
+
.transform((val): Hex => getAddress(val));
|
|
16
|
+
|
|
17
|
+
export const addressNotZeroSchema = addressSchema.refine((val) => val !== zeroAddress, {
|
|
18
|
+
error: 'Must not be zeroAddress',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const bytesSchema = z.custom<Hex>(
|
|
22
|
+
(val) => {
|
|
23
|
+
return typeof val === 'string' && isHex(val);
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
message: 'Invalid hex value',
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export const bytesNotEmptySchema = bytesSchema.refine((val) => val !== '0x', {
|
|
31
|
+
error: 'Must not be empty',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1000) + 7 * 24 * 60 * 60; // 7 days from now
|
|
35
|
+
|
|
11
36
|
const zPermitWithDefaults = z.object({
|
|
12
37
|
name: z.string().optional().default('Unnamed Permit'),
|
|
13
38
|
type: z.enum(['self', 'sharing', 'recipient']),
|
|
14
|
-
issuer:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}),
|
|
22
|
-
expiration: z.number().optional().default(1000000000000),
|
|
23
|
-
recipient: z
|
|
24
|
-
.string()
|
|
25
|
-
.optional()
|
|
26
|
-
.default(zeroAddress)
|
|
27
|
-
.refine((val) => isAddress(val), {
|
|
28
|
-
message: 'Permit recipient :: invalid address',
|
|
29
|
-
}),
|
|
30
|
-
validatorId: z.number().optional().default(0),
|
|
31
|
-
validatorContract: z
|
|
32
|
-
.string()
|
|
33
|
-
.optional()
|
|
34
|
-
.default(zeroAddress)
|
|
35
|
-
.refine((val) => isAddress(val), {
|
|
36
|
-
message: 'Permit validatorContract :: invalid address',
|
|
37
|
-
}),
|
|
38
|
-
issuerSignature: z.string().optional().default('0x'),
|
|
39
|
-
recipientSignature: z.string().optional().default('0x'),
|
|
39
|
+
issuer: addressNotZeroSchema,
|
|
40
|
+
expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
41
|
+
recipient: addressSchema.optional().default(zeroAddress),
|
|
42
|
+
validatorId: z.int().optional().default(0),
|
|
43
|
+
validatorContract: addressSchema.optional().default(zeroAddress),
|
|
44
|
+
issuerSignature: bytesSchema.optional().default('0x'),
|
|
45
|
+
recipientSignature: bytesSchema.optional().default('0x'),
|
|
40
46
|
});
|
|
41
47
|
|
|
42
48
|
const zPermitWithSealingPair = zPermitWithDefaults.extend({
|
|
@@ -50,16 +56,27 @@ type zPermitType = z.infer<typeof zPermitWithDefaults>;
|
|
|
50
56
|
* this check ensures that IF an external validator is applied, that both `validatorId` and `validatorContract` are populated,
|
|
51
57
|
* ELSE ensures that both `validatorId` and `validatorContract` are empty
|
|
52
58
|
*/
|
|
53
|
-
const
|
|
59
|
+
const ExternalValidatorRefinement = [
|
|
54
60
|
(data: zPermitType) =>
|
|
55
61
|
(data.validatorId !== 0 && data.validatorContract !== zeroAddress) ||
|
|
56
62
|
(data.validatorId === 0 && data.validatorContract === zeroAddress),
|
|
57
63
|
{
|
|
58
|
-
|
|
64
|
+
error: 'Permit external validator :: validatorId and validatorContract must either both be set or both be unset.',
|
|
59
65
|
path: ['validatorId', 'validatorContract'] as string[],
|
|
60
66
|
},
|
|
61
67
|
] as const;
|
|
62
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Prevents sharable permit from having the same issuer and recipient
|
|
71
|
+
*/
|
|
72
|
+
const RecipientRefinement = [
|
|
73
|
+
(data: zPermitType) => data.issuer !== data.recipient,
|
|
74
|
+
{
|
|
75
|
+
error: 'Sharing permit :: issuer and recipient must not be the same',
|
|
76
|
+
path: ['issuer', 'recipient'] as string[],
|
|
77
|
+
},
|
|
78
|
+
] as const;
|
|
79
|
+
|
|
63
80
|
// ============================================================================
|
|
64
81
|
// SELF PERMIT VALIDATORS
|
|
65
82
|
// ============================================================================
|
|
@@ -70,68 +87,34 @@ const ValidatorContractRefinement = [
|
|
|
70
87
|
export const SelfPermitOptionsValidator = z
|
|
71
88
|
.object({
|
|
72
89
|
type: z.literal('self').optional().default('self'),
|
|
73
|
-
issuer:
|
|
74
|
-
.string()
|
|
75
|
-
.refine((val) => isAddress(val), {
|
|
76
|
-
message: 'Self permit issuer :: invalid address',
|
|
77
|
-
})
|
|
78
|
-
.refine((val) => val !== zeroAddress, {
|
|
79
|
-
message: 'Self permit issuer :: must not be zeroAddress',
|
|
80
|
-
}),
|
|
90
|
+
issuer: addressNotZeroSchema,
|
|
81
91
|
name: z.string().optional().default('Unnamed Permit'),
|
|
82
|
-
expiration: z.
|
|
83
|
-
recipient:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
message: 'Self permit recipient :: invalid address',
|
|
89
|
-
})
|
|
90
|
-
.refine((val) => val === zeroAddress, {
|
|
91
|
-
message: 'Self permit recipient :: must be zeroAddress',
|
|
92
|
-
}),
|
|
93
|
-
validatorId: z.number().optional().default(0),
|
|
94
|
-
validatorContract: z
|
|
95
|
-
.string()
|
|
96
|
-
.optional()
|
|
97
|
-
.default(zeroAddress)
|
|
98
|
-
.refine((val) => isAddress(val), {
|
|
99
|
-
message: 'Self permit validatorContract :: invalid address',
|
|
100
|
-
}),
|
|
101
|
-
issuerSignature: z
|
|
102
|
-
.string()
|
|
103
|
-
.optional()
|
|
104
|
-
.default('0x')
|
|
105
|
-
.refine((val) => is0xPrefixed(val), {
|
|
106
|
-
message: 'Self permit issuerSignature :: must be 0x prefixed',
|
|
107
|
-
}),
|
|
108
|
-
recipientSignature: z
|
|
109
|
-
.string()
|
|
110
|
-
.optional()
|
|
111
|
-
.default('0x')
|
|
112
|
-
.refine((val) => is0xPrefixed(val), {
|
|
113
|
-
message: 'Self permit recipientSignature :: must be 0x prefixed',
|
|
114
|
-
}),
|
|
92
|
+
expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
93
|
+
recipient: addressSchema.optional().default(zeroAddress),
|
|
94
|
+
validatorId: z.int().optional().default(0),
|
|
95
|
+
validatorContract: addressSchema.optional().default(zeroAddress),
|
|
96
|
+
issuerSignature: bytesSchema.optional().default('0x'),
|
|
97
|
+
recipientSignature: bytesSchema.optional().default('0x'),
|
|
115
98
|
})
|
|
116
|
-
.refine(...
|
|
99
|
+
.refine(...ExternalValidatorRefinement);
|
|
117
100
|
|
|
118
101
|
/**
|
|
119
102
|
* Validator for fully formed self permits
|
|
120
103
|
*/
|
|
121
104
|
export const SelfPermitValidator = zPermitWithSealingPair
|
|
122
105
|
.refine((data) => data.type === 'self', {
|
|
123
|
-
|
|
106
|
+
error: "Type must be 'self'",
|
|
124
107
|
})
|
|
125
108
|
.refine((data) => data.recipient === zeroAddress, {
|
|
126
|
-
|
|
109
|
+
error: 'Recipient must be zeroAddress',
|
|
127
110
|
})
|
|
128
111
|
.refine((data) => data.issuerSignature !== '0x', {
|
|
129
|
-
|
|
112
|
+
error: 'IssuerSignature must be populated',
|
|
130
113
|
})
|
|
131
114
|
.refine((data) => data.recipientSignature === '0x', {
|
|
132
|
-
|
|
115
|
+
error: 'RecipientSignature must be empty',
|
|
133
116
|
})
|
|
134
|
-
.refine(...
|
|
117
|
+
.refine(...ExternalValidatorRefinement);
|
|
135
118
|
|
|
136
119
|
// ============================================================================
|
|
137
120
|
// SHARING PERMIT VALIDATORS
|
|
@@ -143,66 +126,35 @@ export const SelfPermitValidator = zPermitWithSealingPair
|
|
|
143
126
|
export const SharingPermitOptionsValidator = z
|
|
144
127
|
.object({
|
|
145
128
|
type: z.literal('sharing').optional().default('sharing'),
|
|
146
|
-
issuer:
|
|
147
|
-
|
|
148
|
-
.refine((val) => isAddress(val), {
|
|
149
|
-
message: 'Sharing permit issuer :: invalid address',
|
|
150
|
-
})
|
|
151
|
-
.refine((val) => val !== zeroAddress, {
|
|
152
|
-
message: 'Sharing permit issuer :: must not be zeroAddress',
|
|
153
|
-
}),
|
|
154
|
-
recipient: z
|
|
155
|
-
.string()
|
|
156
|
-
.refine((val) => isAddress(val), {
|
|
157
|
-
message: 'Sharing permit recipient :: invalid address',
|
|
158
|
-
})
|
|
159
|
-
.refine((val) => val !== zeroAddress, {
|
|
160
|
-
message: 'Sharing permit recipient :: must not be zeroAddress',
|
|
161
|
-
}),
|
|
129
|
+
issuer: addressNotZeroSchema,
|
|
130
|
+
recipient: addressNotZeroSchema,
|
|
162
131
|
name: z.string().optional().default('Unnamed Permit'),
|
|
163
|
-
expiration: z.
|
|
164
|
-
validatorId: z.
|
|
165
|
-
validatorContract:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
.default(zeroAddress)
|
|
169
|
-
.refine((val) => isAddress(val), {
|
|
170
|
-
message: 'Sharing permit validatorContract :: invalid address',
|
|
171
|
-
}),
|
|
172
|
-
issuerSignature: z
|
|
173
|
-
.string()
|
|
174
|
-
.optional()
|
|
175
|
-
.default('0x')
|
|
176
|
-
.refine((val) => is0xPrefixed(val), {
|
|
177
|
-
message: 'Sharing permit issuerSignature :: must be 0x prefixed',
|
|
178
|
-
}),
|
|
179
|
-
recipientSignature: z
|
|
180
|
-
.string()
|
|
181
|
-
.optional()
|
|
182
|
-
.default('0x')
|
|
183
|
-
.refine((val) => is0xPrefixed(val), {
|
|
184
|
-
message: 'Sharing permit recipientSignature :: must be 0x prefixed',
|
|
185
|
-
}),
|
|
132
|
+
expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
133
|
+
validatorId: z.int().optional().default(0),
|
|
134
|
+
validatorContract: addressSchema.optional().default(zeroAddress),
|
|
135
|
+
issuerSignature: bytesSchema.optional().default('0x'),
|
|
136
|
+
recipientSignature: bytesSchema.optional().default('0x'),
|
|
186
137
|
})
|
|
187
|
-
.refine(...
|
|
138
|
+
.refine(...RecipientRefinement)
|
|
139
|
+
.refine(...ExternalValidatorRefinement);
|
|
188
140
|
|
|
189
141
|
/**
|
|
190
142
|
* Validator for fully formed sharing permits
|
|
191
143
|
*/
|
|
192
144
|
export const SharingPermitValidator = zPermitWithSealingPair
|
|
193
145
|
.refine((data) => data.type === 'sharing', {
|
|
194
|
-
|
|
146
|
+
error: "Type must be 'sharing'",
|
|
195
147
|
})
|
|
196
148
|
.refine((data) => data.recipient !== zeroAddress, {
|
|
197
|
-
|
|
149
|
+
error: 'Recipient must not be zeroAddress',
|
|
198
150
|
})
|
|
199
151
|
.refine((data) => data.issuerSignature !== '0x', {
|
|
200
|
-
|
|
152
|
+
error: 'IssuerSignature must be populated',
|
|
201
153
|
})
|
|
202
154
|
.refine((data) => data.recipientSignature === '0x', {
|
|
203
|
-
|
|
155
|
+
error: 'RecipientSignature must be empty',
|
|
204
156
|
})
|
|
205
|
-
.refine(...
|
|
157
|
+
.refine(...ExternalValidatorRefinement);
|
|
206
158
|
|
|
207
159
|
// ============================================================================
|
|
208
160
|
// IMPORT/RECIPIENT PERMIT VALIDATORS
|
|
@@ -214,101 +166,87 @@ export const SharingPermitValidator = zPermitWithSealingPair
|
|
|
214
166
|
export const ImportPermitOptionsValidator = z
|
|
215
167
|
.object({
|
|
216
168
|
type: z.literal('recipient').optional().default('recipient'),
|
|
217
|
-
issuer:
|
|
218
|
-
|
|
219
|
-
.refine((val) => isAddress(val), {
|
|
220
|
-
message: 'Import permit issuer :: invalid address',
|
|
221
|
-
})
|
|
222
|
-
.refine((val) => val !== zeroAddress, {
|
|
223
|
-
message: 'Import permit issuer :: must not be zeroAddress',
|
|
224
|
-
}),
|
|
225
|
-
recipient: z
|
|
226
|
-
.string()
|
|
227
|
-
.refine((val) => isAddress(val), {
|
|
228
|
-
message: 'Import permit recipient :: invalid address',
|
|
229
|
-
})
|
|
230
|
-
.refine((val) => val !== zeroAddress, {
|
|
231
|
-
message: 'Import permit recipient :: must not be zeroAddress',
|
|
232
|
-
}),
|
|
233
|
-
issuerSignature: z
|
|
234
|
-
.string()
|
|
235
|
-
.refine((val) => is0xPrefixed(val), {
|
|
236
|
-
message: 'Import permit issuerSignature :: must be 0x prefixed',
|
|
237
|
-
})
|
|
238
|
-
.refine((val) => val !== '0x', {
|
|
239
|
-
message: 'Import permit :: issuerSignature must be provided',
|
|
240
|
-
}),
|
|
169
|
+
issuer: addressNotZeroSchema,
|
|
170
|
+
recipient: addressNotZeroSchema,
|
|
241
171
|
name: z.string().optional().default('Unnamed Permit'),
|
|
242
|
-
expiration: z.
|
|
243
|
-
validatorId: z.
|
|
244
|
-
validatorContract:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
.default(zeroAddress)
|
|
248
|
-
.refine((val) => isAddress(val), {
|
|
249
|
-
message: 'Import permit validatorContract :: invalid address',
|
|
250
|
-
}),
|
|
251
|
-
recipientSignature: z
|
|
252
|
-
.string()
|
|
253
|
-
.optional()
|
|
254
|
-
.default('0x')
|
|
255
|
-
.refine((val) => is0xPrefixed(val), {
|
|
256
|
-
message: 'Import permit recipientSignature :: must be 0x prefixed',
|
|
257
|
-
}),
|
|
172
|
+
expiration: z.int(),
|
|
173
|
+
validatorId: z.int().optional().default(0),
|
|
174
|
+
validatorContract: addressSchema.optional().default(zeroAddress),
|
|
175
|
+
issuerSignature: bytesNotEmptySchema,
|
|
176
|
+
recipientSignature: bytesSchema.optional().default('0x'),
|
|
258
177
|
})
|
|
259
|
-
.refine(...
|
|
178
|
+
.refine(...ExternalValidatorRefinement);
|
|
260
179
|
|
|
261
180
|
/**
|
|
262
181
|
* Validator for fully formed import/recipient permits
|
|
263
182
|
*/
|
|
264
183
|
export const ImportPermitValidator = zPermitWithSealingPair
|
|
265
184
|
.refine((data) => data.type === 'recipient', {
|
|
266
|
-
|
|
185
|
+
error: "Type must be 'recipient'",
|
|
267
186
|
})
|
|
268
187
|
.refine((data) => data.recipient !== zeroAddress, {
|
|
269
|
-
|
|
188
|
+
error: 'Recipient must not be zeroAddress',
|
|
270
189
|
})
|
|
271
190
|
.refine((data) => data.issuerSignature !== '0x', {
|
|
272
|
-
|
|
191
|
+
error: 'IssuerSignature must be populated',
|
|
273
192
|
})
|
|
274
193
|
.refine((data) => data.recipientSignature !== '0x', {
|
|
275
|
-
|
|
194
|
+
error: 'RecipientSignature must be populated',
|
|
276
195
|
})
|
|
277
|
-
.refine(...
|
|
196
|
+
.refine(...ExternalValidatorRefinement);
|
|
278
197
|
|
|
279
198
|
// ============================================================================
|
|
280
199
|
// VALIDATION FUNCTIONS
|
|
281
200
|
// ============================================================================
|
|
282
201
|
|
|
202
|
+
const safeParseAndThrowFormatted = <T extends z.ZodTypeAny>(schema: T, data: unknown, message: string): z.output<T> => {
|
|
203
|
+
const result = schema.safeParse(data);
|
|
204
|
+
if (!result.success) {
|
|
205
|
+
throw new Error(`${message}: ${z.prettifyError(result.error)}`, { cause: result.error });
|
|
206
|
+
}
|
|
207
|
+
return result.data;
|
|
208
|
+
};
|
|
209
|
+
|
|
283
210
|
/**
|
|
284
211
|
* Validates self permit creation options
|
|
285
212
|
*/
|
|
286
|
-
export const validateSelfPermitOptions = (options: any) =>
|
|
287
|
-
|
|
213
|
+
export const validateSelfPermitOptions = (options: any) => {
|
|
214
|
+
return safeParseAndThrowFormatted(SelfPermitOptionsValidator, options, 'Invalid self permit options');
|
|
215
|
+
};
|
|
288
216
|
/**
|
|
289
217
|
* Validates sharing permit creation options
|
|
290
218
|
*/
|
|
291
|
-
export const validateSharingPermitOptions = (options: any) =>
|
|
219
|
+
export const validateSharingPermitOptions = (options: any) => {
|
|
220
|
+
return safeParseAndThrowFormatted(SharingPermitOptionsValidator, options, 'Invalid sharing permit options');
|
|
221
|
+
};
|
|
292
222
|
|
|
293
223
|
/**
|
|
294
224
|
* Validates import permit creation options
|
|
295
225
|
*/
|
|
296
|
-
export const validateImportPermitOptions = (options: any) =>
|
|
226
|
+
export const validateImportPermitOptions = (options: any) => {
|
|
227
|
+
return safeParseAndThrowFormatted(ImportPermitOptionsValidator, options, 'Invalid import permit options');
|
|
228
|
+
};
|
|
297
229
|
|
|
298
230
|
/**
|
|
299
231
|
* Validates a fully formed self permit
|
|
300
232
|
*/
|
|
301
|
-
export const validateSelfPermit = (permit: any) =>
|
|
233
|
+
export const validateSelfPermit = (permit: any) => {
|
|
234
|
+
return safeParseAndThrowFormatted(SelfPermitValidator, permit, 'Invalid self permit');
|
|
235
|
+
};
|
|
302
236
|
|
|
303
237
|
/**
|
|
304
238
|
* Validates a fully formed sharing permit
|
|
305
239
|
*/
|
|
306
|
-
export const validateSharingPermit = (permit: any) =>
|
|
240
|
+
export const validateSharingPermit = (permit: any) => {
|
|
241
|
+
return safeParseAndThrowFormatted(SharingPermitValidator, permit, 'Invalid sharing permit');
|
|
242
|
+
};
|
|
307
243
|
|
|
308
244
|
/**
|
|
309
245
|
* Validates a fully formed import/recipient permit
|
|
310
246
|
*/
|
|
311
|
-
export const validateImportPermit = (permit: any) =>
|
|
247
|
+
export const validateImportPermit = (permit: any) => {
|
|
248
|
+
return safeParseAndThrowFormatted(ImportPermitValidator, permit, 'Invalid import permit');
|
|
249
|
+
};
|
|
312
250
|
|
|
313
251
|
/**
|
|
314
252
|
* Simple validation functions for common checks
|
package/web/client.web.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CofhesdkClient } from '@/core';
|
|
1
|
+
import { CofhesdkErrorCode, CofhesdkError, type CofhesdkClient } from '@/core';
|
|
2
2
|
import { arbSepolia as cofhesdkArbSepolia } from '@/chains';
|
|
3
3
|
|
|
4
4
|
import { describe, it, expect, beforeAll, beforeEach, vi } from 'vitest';
|
|
@@ -60,11 +60,16 @@ describe('@cofhe/web - Client', () => {
|
|
|
60
60
|
});
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
describe('Environment', () => {
|
|
64
|
+
it('should have the correct environment', () => {
|
|
65
|
+
expect(cofhesdkClient.config.environment).toBe('web');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
63
69
|
describe('Connection', () => {
|
|
64
70
|
it('should connect to real chain', async () => {
|
|
65
|
-
|
|
71
|
+
await cofhesdkClient.connect(publicClient, walletClient);
|
|
66
72
|
|
|
67
|
-
expect(result.success).toBe(true);
|
|
68
73
|
expect(cofhesdkClient.connected).toBe(true);
|
|
69
74
|
|
|
70
75
|
const snapshot = cofhesdkClient.getSnapshot();
|
|
@@ -74,15 +79,17 @@ describe('@cofhe/web - Client', () => {
|
|
|
74
79
|
}, 30000);
|
|
75
80
|
|
|
76
81
|
it('should handle network errors', async () => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
try {
|
|
83
|
+
await cofhesdkClient.connect(
|
|
84
|
+
{
|
|
85
|
+
getChainId: vi.fn().mockRejectedValue(new Error('Network error')),
|
|
86
|
+
} as unknown as PublicClient,
|
|
87
|
+
walletClient
|
|
88
|
+
);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
expect(error).toBeInstanceOf(CofhesdkError);
|
|
91
|
+
expect((error as CofhesdkError).code).toBe(CofhesdkErrorCode.PublicWalletGetChainIdFailed);
|
|
92
|
+
}
|
|
86
93
|
}, 30000);
|
|
87
94
|
});
|
|
88
95
|
|
|
@@ -113,23 +120,11 @@ describe('@cofhe/web - Client', () => {
|
|
|
113
120
|
}, 30000);
|
|
114
121
|
});
|
|
115
122
|
|
|
116
|
-
describe('Initialization Results', () => {
|
|
117
|
-
it('should have keyFetchResult promise', () => {
|
|
118
|
-
expect(cofhesdkClient.initializationResults).toBeDefined();
|
|
119
|
-
expect(cofhesdkClient.initializationResults.keyFetchResult).toBeInstanceOf(Promise);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('should resolve keyFetchResult', async () => {
|
|
123
|
-
const result = await cofhesdkClient.initializationResults.keyFetchResult;
|
|
124
|
-
expect(result.success).toBe(true);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
123
|
describe('Builder Creation', () => {
|
|
129
124
|
it('should create encrypt builder after connection', async () => {
|
|
130
125
|
await cofhesdkClient.connect(publicClient, walletClient);
|
|
131
126
|
|
|
132
|
-
const builder = cofhesdkClient.encryptInputs([{ data: 100n, utype: 2 }]);
|
|
127
|
+
const builder = cofhesdkClient.encryptInputs([{ data: 100n, utype: 2, securityZone: 0 }]);
|
|
133
128
|
|
|
134
129
|
expect(builder).toBeDefined();
|
|
135
130
|
expect(typeof builder.setChainId).toBe('function');
|
package/web/config.web.test.ts
CHANGED
|
@@ -42,14 +42,12 @@ describe('@cofhe/web - Config', () => {
|
|
|
42
42
|
it('should preserve all other config options', () => {
|
|
43
43
|
const config = createCofhesdkConfig({
|
|
44
44
|
supportedChains: [arbSepolia],
|
|
45
|
-
fheKeysPrefetching: 'OFF',
|
|
46
45
|
mocks: {
|
|
47
46
|
sealOutputDelay: 500,
|
|
48
47
|
},
|
|
49
48
|
});
|
|
50
49
|
|
|
51
50
|
expect(config.supportedChains).toEqual([arbSepolia]);
|
|
52
|
-
expect(config.fheKeysPrefetching).toBe('OFF');
|
|
53
51
|
expect(config.mocks.sealOutputDelay).toBe(500);
|
|
54
52
|
expect(config.fheKeyStorage).toBeDefined();
|
|
55
53
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { arbSepolia as cofhesdkArbSepolia } from '@/chains';
|
|
2
|
-
import { Encryptable, FheTypes, type CofhesdkClient,
|
|
2
|
+
import { Encryptable, FheTypes, type CofhesdkClient, CofhesdkErrorCode, CofhesdkError } from '@/core';
|
|
3
3
|
|
|
4
4
|
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
|
|
5
5
|
import type { PublicClient, WalletClient } from 'viem';
|
|
@@ -11,22 +11,6 @@ import { createCofhesdkClient, createCofhesdkConfig } from './index.js';
|
|
|
11
11
|
// Real test setup - runs in browser with real tfhe
|
|
12
12
|
const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
|
|
13
13
|
|
|
14
|
-
const expectResultSuccess = <T>(result: Result<T>): T => {
|
|
15
|
-
expect(result.success, `Result error: ${result.error?.toString()}`).toBe(true);
|
|
16
|
-
return result.data!;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const expectResultError = <T>(result: Result<T>, errorCode?: CofhesdkErrorCode): void => {
|
|
20
|
-
expect(result.success).toBe(false);
|
|
21
|
-
expect(result.data).toBe(null);
|
|
22
|
-
expect(result.error).not.toBe(null);
|
|
23
|
-
const error = result.error as CofhesdkError;
|
|
24
|
-
expect(error).toBeInstanceOf(CofhesdkError);
|
|
25
|
-
if (errorCode) {
|
|
26
|
-
expect(error.code, `Result error: ${result.error?.toString()}`).toBe(errorCode);
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
14
|
describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
|
|
31
15
|
let cofhesdkClient: CofhesdkClient;
|
|
32
16
|
let publicClient: PublicClient;
|
|
@@ -60,22 +44,19 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
|
|
|
60
44
|
|
|
61
45
|
// This will trigger real TFHE initialization in browser
|
|
62
46
|
const result = await cofhesdkClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
|
|
63
|
-
const encrypted = expectResultSuccess(result);
|
|
64
47
|
|
|
65
48
|
// If we get here, TFHE was initialized successfully
|
|
66
|
-
expect(
|
|
49
|
+
expect(result).toBeDefined();
|
|
67
50
|
}, 60000); // Longer timeout for real operations
|
|
68
51
|
|
|
69
52
|
it('should handle multiple encryptions without re-initializing', async () => {
|
|
70
53
|
await cofhesdkClient.connect(publicClient, walletClient);
|
|
71
54
|
|
|
72
55
|
// First encryption
|
|
73
|
-
|
|
74
|
-
expectResultSuccess(result1);
|
|
56
|
+
expect(cofhesdkClient.encryptInputs([Encryptable.uint128(100n)]).encrypt()).resolves.not.toThrow();
|
|
75
57
|
|
|
76
58
|
// Second encryption should reuse initialization
|
|
77
|
-
|
|
78
|
-
expectResultSuccess(result2);
|
|
59
|
+
expect(cofhesdkClient.encryptInputs([Encryptable.uint64(50n)]).encrypt()).resolves.not.toThrow();
|
|
79
60
|
}, 60000);
|
|
80
61
|
});
|
|
81
62
|
|
|
@@ -84,15 +65,15 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
|
|
|
84
65
|
await cofhesdkClient.connect(publicClient, walletClient);
|
|
85
66
|
|
|
86
67
|
const result = await cofhesdkClient.encryptInputs([Encryptable.bool(true)]).encrypt();
|
|
87
|
-
const encrypted = expectResultSuccess(result);
|
|
88
68
|
|
|
89
|
-
expect(
|
|
90
|
-
expect(
|
|
91
|
-
expect(
|
|
92
|
-
expect(
|
|
93
|
-
expect(
|
|
94
|
-
expect(
|
|
95
|
-
expect(
|
|
69
|
+
expect(result).toBeDefined();
|
|
70
|
+
expect(result.length).toBe(1);
|
|
71
|
+
expect(result[0].utype).toBe(FheTypes.Bool);
|
|
72
|
+
expect(result[0].ctHash).toBeDefined();
|
|
73
|
+
expect(typeof result[0].ctHash).toBe('bigint');
|
|
74
|
+
expect(result[0].signature).toBeDefined();
|
|
75
|
+
expect(typeof result[0].signature).toBe('string');
|
|
76
|
+
expect(result[0].securityZone).toBe(0);
|
|
96
77
|
}, 60000);
|
|
97
78
|
|
|
98
79
|
it('should encrypt all supported types together', async () => {
|
|
@@ -109,17 +90,17 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
|
|
|
109
90
|
];
|
|
110
91
|
|
|
111
92
|
const result = await cofhesdkClient.encryptInputs(inputs).encrypt();
|
|
112
|
-
|
|
93
|
+
expect(result).toBeDefined();
|
|
113
94
|
|
|
114
|
-
expect(
|
|
95
|
+
expect(result.length).toBe(7);
|
|
115
96
|
// Verify each type
|
|
116
|
-
expect(
|
|
117
|
-
expect(
|
|
118
|
-
expect(
|
|
119
|
-
expect(
|
|
120
|
-
expect(
|
|
121
|
-
expect(
|
|
122
|
-
expect(
|
|
97
|
+
expect(result[0].utype).toBe(FheTypes.Bool);
|
|
98
|
+
expect(result[1].utype).toBe(FheTypes.Uint8);
|
|
99
|
+
expect(result[2].utype).toBe(FheTypes.Uint16);
|
|
100
|
+
expect(result[3].utype).toBe(FheTypes.Uint32);
|
|
101
|
+
expect(result[4].utype).toBe(FheTypes.Uint64);
|
|
102
|
+
expect(result[5].utype).toBe(FheTypes.Uint128);
|
|
103
|
+
expect(result[6].utype).toBe(FheTypes.Uint160);
|
|
123
104
|
}, 90000); // Longer timeout for multiple encryptions
|
|
124
105
|
});
|
|
125
106
|
|
|
@@ -128,14 +109,13 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
|
|
|
128
109
|
await cofhesdkClient.connect(publicClient, walletClient);
|
|
129
110
|
|
|
130
111
|
const snapshot = cofhesdkClient.getSnapshot();
|
|
131
|
-
const
|
|
112
|
+
const encrypted = await cofhesdkClient
|
|
132
113
|
.encryptInputs([Encryptable.uint128(100n)])
|
|
133
114
|
.setChainId(snapshot.chainId!)
|
|
134
115
|
.setAccount(snapshot.account!)
|
|
135
116
|
.setSecurityZone(0)
|
|
136
117
|
.encrypt();
|
|
137
118
|
|
|
138
|
-
const encrypted = expectResultSuccess(result);
|
|
139
119
|
expect(encrypted.length).toBe(1);
|
|
140
120
|
expect(encrypted[0].utype).toBe(FheTypes.Uint128);
|
|
141
121
|
}, 60000);
|
|
@@ -144,9 +124,12 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
|
|
|
144
124
|
describe('Browser Error Handling', () => {
|
|
145
125
|
it('should fail gracefully when not connected', async () => {
|
|
146
126
|
// Don't connect the client
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
127
|
+
try {
|
|
128
|
+
const promise = cofhesdkClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
|
|
129
|
+
} catch (error) {
|
|
130
|
+
expect(error).toBeInstanceOf(CofhesdkError);
|
|
131
|
+
expect((error as CofhesdkError).code).toBe(CofhesdkErrorCode.NotConnected);
|
|
132
|
+
}
|
|
150
133
|
}, 30000);
|
|
151
134
|
|
|
152
135
|
it('should handle invalid CoFHE URL', async () => {
|
|
@@ -158,18 +141,13 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
|
|
|
158
141
|
verifierUrl: 'http://invalid-verifier-url.local',
|
|
159
142
|
},
|
|
160
143
|
],
|
|
161
|
-
fheKeysPrefetching: 'OFF',
|
|
162
144
|
});
|
|
163
145
|
|
|
164
146
|
const badClient = createCofhesdkClient(badConfig);
|
|
165
147
|
await badClient.connect(publicClient, walletClient);
|
|
166
148
|
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
expect(result.success).toBe(false);
|
|
170
|
-
if (!result.success) {
|
|
171
|
-
expect(result.error).toBeDefined();
|
|
172
|
-
}
|
|
149
|
+
const promise = badClient.encryptInputs([Encryptable.uint128(100n)]).encrypt();
|
|
150
|
+
expect(promise).rejects.toThrow();
|
|
173
151
|
}, 60000);
|
|
174
152
|
});
|
|
175
153
|
|
|
@@ -181,8 +159,7 @@ describe('@cofhe/web - Encrypt Inputs Browser Tests', () => {
|
|
|
181
159
|
|
|
182
160
|
// Perform 5 encryptions
|
|
183
161
|
for (let i = 0; i < 5; i++) {
|
|
184
|
-
|
|
185
|
-
expectResultSuccess(result);
|
|
162
|
+
await cofhesdkClient.encryptInputs([Encryptable.uint128(BigInt(i))]).encrypt();
|
|
186
163
|
}
|
|
187
164
|
|
|
188
165
|
const duration = Date.now() - start;
|