@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/dist/permits.cjs
CHANGED
|
@@ -76,9 +76,6 @@ function isBigIntOrNumber(value) {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
function is0xPrefixed(value) {
|
|
80
|
-
return value.startsWith("0x");
|
|
81
|
-
}
|
|
82
79
|
|
|
83
80
|
// permits/sealing.ts
|
|
84
81
|
var PRIVATE_KEY_LENGTH = 64;
|
|
@@ -158,7 +155,7 @@ var SealingKey = class _SealingKey {
|
|
|
158
155
|
};
|
|
159
156
|
};
|
|
160
157
|
};
|
|
161
|
-
var GenerateSealingKey =
|
|
158
|
+
var GenerateSealingKey = () => {
|
|
162
159
|
const sodiumKeypair = nacl__namespace.box.keyPair();
|
|
163
160
|
return new SealingKey(toHexString(sodiumKeypair.secretKey), toHexString(sodiumKeypair.publicKey));
|
|
164
161
|
};
|
|
@@ -166,145 +163,137 @@ var SerializedSealingPair = zod.z.object({
|
|
|
166
163
|
privateKey: zod.z.string(),
|
|
167
164
|
publicKey: zod.z.string()
|
|
168
165
|
});
|
|
166
|
+
var addressSchema = zod.z.string().refine((val) => viem.isAddress(val), {
|
|
167
|
+
error: "Invalid address"
|
|
168
|
+
}).transform((val) => viem.getAddress(val));
|
|
169
|
+
var addressNotZeroSchema = addressSchema.refine((val) => val !== viem.zeroAddress, {
|
|
170
|
+
error: "Must not be zeroAddress"
|
|
171
|
+
});
|
|
172
|
+
var bytesSchema = zod.z.custom(
|
|
173
|
+
(val) => {
|
|
174
|
+
return typeof val === "string" && viem.isHex(val);
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
message: "Invalid hex value"
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
var bytesNotEmptySchema = bytesSchema.refine((val) => val !== "0x", {
|
|
181
|
+
error: "Must not be empty"
|
|
182
|
+
});
|
|
183
|
+
var DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1e3) + 7 * 24 * 60 * 60;
|
|
169
184
|
var zPermitWithDefaults = zod.z.object({
|
|
170
185
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
171
186
|
type: zod.z.enum(["self", "sharing", "recipient"]),
|
|
172
|
-
issuer:
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
message: "Permit recipient :: invalid address"
|
|
180
|
-
}),
|
|
181
|
-
validatorId: zod.z.number().optional().default(0),
|
|
182
|
-
validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
|
|
183
|
-
message: "Permit validatorContract :: invalid address"
|
|
184
|
-
}),
|
|
185
|
-
issuerSignature: zod.z.string().optional().default("0x"),
|
|
186
|
-
recipientSignature: zod.z.string().optional().default("0x")
|
|
187
|
+
issuer: addressNotZeroSchema,
|
|
188
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
189
|
+
recipient: addressSchema.optional().default(viem.zeroAddress),
|
|
190
|
+
validatorId: zod.z.int().optional().default(0),
|
|
191
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
192
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
193
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
187
194
|
});
|
|
188
195
|
var zPermitWithSealingPair = zPermitWithDefaults.extend({
|
|
189
196
|
sealingPair: SerializedSealingPair.optional()
|
|
190
197
|
});
|
|
191
|
-
var
|
|
198
|
+
var ExternalValidatorRefinement = [
|
|
192
199
|
(data) => data.validatorId !== 0 && data.validatorContract !== viem.zeroAddress || data.validatorId === 0 && data.validatorContract === viem.zeroAddress,
|
|
193
200
|
{
|
|
194
|
-
|
|
201
|
+
error: "Permit external validator :: validatorId and validatorContract must either both be set or both be unset.",
|
|
195
202
|
path: ["validatorId", "validatorContract"]
|
|
196
203
|
}
|
|
197
204
|
];
|
|
205
|
+
var RecipientRefinement = [
|
|
206
|
+
(data) => data.issuer !== data.recipient,
|
|
207
|
+
{
|
|
208
|
+
error: "Sharing permit :: issuer and recipient must not be the same",
|
|
209
|
+
path: ["issuer", "recipient"]
|
|
210
|
+
}
|
|
211
|
+
];
|
|
198
212
|
var SelfPermitOptionsValidator = zod.z.object({
|
|
199
213
|
type: zod.z.literal("self").optional().default("self"),
|
|
200
|
-
issuer:
|
|
201
|
-
message: "Self permit issuer :: invalid address"
|
|
202
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
203
|
-
message: "Self permit issuer :: must not be zeroAddress"
|
|
204
|
-
}),
|
|
214
|
+
issuer: addressNotZeroSchema,
|
|
205
215
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
206
|
-
expiration: zod.z.
|
|
207
|
-
recipient:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
validatorContract: zod.z.string().optional().default(viem.zeroAddress).refine((val) => viem.isAddress(val), {
|
|
214
|
-
message: "Self permit validatorContract :: invalid address"
|
|
215
|
-
}),
|
|
216
|
-
issuerSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
217
|
-
message: "Self permit issuerSignature :: must be 0x prefixed"
|
|
218
|
-
}),
|
|
219
|
-
recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
220
|
-
message: "Self permit recipientSignature :: must be 0x prefixed"
|
|
221
|
-
})
|
|
222
|
-
}).refine(...ValidatorContractRefinement);
|
|
216
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
217
|
+
recipient: addressSchema.optional().default(viem.zeroAddress),
|
|
218
|
+
validatorId: zod.z.int().optional().default(0),
|
|
219
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
220
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
221
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
222
|
+
}).refine(...ExternalValidatorRefinement);
|
|
223
223
|
var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "self", {
|
|
224
|
-
|
|
224
|
+
error: "Type must be 'self'"
|
|
225
225
|
}).refine((data) => data.recipient === viem.zeroAddress, {
|
|
226
|
-
|
|
226
|
+
error: "Recipient must be zeroAddress"
|
|
227
227
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
228
|
-
|
|
228
|
+
error: "IssuerSignature must be populated"
|
|
229
229
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
230
|
-
|
|
231
|
-
}).refine(...
|
|
230
|
+
error: "RecipientSignature must be empty"
|
|
231
|
+
}).refine(...ExternalValidatorRefinement);
|
|
232
232
|
var SharingPermitOptionsValidator = zod.z.object({
|
|
233
233
|
type: zod.z.literal("sharing").optional().default("sharing"),
|
|
234
|
-
issuer:
|
|
235
|
-
|
|
236
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
237
|
-
message: "Sharing permit issuer :: must not be zeroAddress"
|
|
238
|
-
}),
|
|
239
|
-
recipient: zod.z.string().refine((val) => viem.isAddress(val), {
|
|
240
|
-
message: "Sharing permit recipient :: invalid address"
|
|
241
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
242
|
-
message: "Sharing permit recipient :: must not be zeroAddress"
|
|
243
|
-
}),
|
|
234
|
+
issuer: addressNotZeroSchema,
|
|
235
|
+
recipient: addressNotZeroSchema,
|
|
244
236
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
245
|
-
expiration: zod.z.
|
|
246
|
-
validatorId: zod.z.
|
|
247
|
-
validatorContract:
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
message: "Sharing permit issuerSignature :: must be 0x prefixed"
|
|
252
|
-
}),
|
|
253
|
-
recipientSignature: zod.z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
254
|
-
message: "Sharing permit recipientSignature :: must be 0x prefixed"
|
|
255
|
-
})
|
|
256
|
-
}).refine(...ValidatorContractRefinement);
|
|
237
|
+
expiration: zod.z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
238
|
+
validatorId: zod.z.int().optional().default(0),
|
|
239
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
240
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
241
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
242
|
+
}).refine(...RecipientRefinement).refine(...ExternalValidatorRefinement);
|
|
257
243
|
var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "sharing", {
|
|
258
|
-
|
|
244
|
+
error: "Type must be 'sharing'"
|
|
259
245
|
}).refine((data) => data.recipient !== viem.zeroAddress, {
|
|
260
|
-
|
|
246
|
+
error: "Recipient must not be zeroAddress"
|
|
261
247
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
262
|
-
|
|
248
|
+
error: "IssuerSignature must be populated"
|
|
263
249
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
264
|
-
|
|
265
|
-
}).refine(...
|
|
250
|
+
error: "RecipientSignature must be empty"
|
|
251
|
+
}).refine(...ExternalValidatorRefinement);
|
|
266
252
|
var ImportPermitOptionsValidator = zod.z.object({
|
|
267
253
|
type: zod.z.literal("recipient").optional().default("recipient"),
|
|
268
|
-
issuer:
|
|
269
|
-
|
|
270
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
271
|
-
message: "Import permit issuer :: must not be zeroAddress"
|
|
272
|
-
}),
|
|
273
|
-
recipient: zod.z.string().refine((val) => viem.isAddress(val), {
|
|
274
|
-
message: "Import permit recipient :: invalid address"
|
|
275
|
-
}).refine((val) => val !== viem.zeroAddress, {
|
|
276
|
-
message: "Import permit recipient :: must not be zeroAddress"
|
|
277
|
-
}),
|
|
278
|
-
issuerSignature: zod.z.string().refine((val) => is0xPrefixed(val), {
|
|
279
|
-
message: "Import permit issuerSignature :: must be 0x prefixed"
|
|
280
|
-
}).refine((val) => val !== "0x", {
|
|
281
|
-
message: "Import permit :: issuerSignature must be provided"
|
|
282
|
-
}),
|
|
254
|
+
issuer: addressNotZeroSchema,
|
|
255
|
+
recipient: addressNotZeroSchema,
|
|
283
256
|
name: zod.z.string().optional().default("Unnamed Permit"),
|
|
284
|
-
expiration: zod.z.
|
|
285
|
-
validatorId: zod.z.
|
|
286
|
-
validatorContract:
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
message: "Import permit recipientSignature :: must be 0x prefixed"
|
|
291
|
-
})
|
|
292
|
-
}).refine(...ValidatorContractRefinement);
|
|
257
|
+
expiration: zod.z.int(),
|
|
258
|
+
validatorId: zod.z.int().optional().default(0),
|
|
259
|
+
validatorContract: addressSchema.optional().default(viem.zeroAddress),
|
|
260
|
+
issuerSignature: bytesNotEmptySchema,
|
|
261
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
262
|
+
}).refine(...ExternalValidatorRefinement);
|
|
293
263
|
var ImportPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "recipient", {
|
|
294
|
-
|
|
264
|
+
error: "Type must be 'recipient'"
|
|
295
265
|
}).refine((data) => data.recipient !== viem.zeroAddress, {
|
|
296
|
-
|
|
266
|
+
error: "Recipient must not be zeroAddress"
|
|
297
267
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
298
|
-
|
|
268
|
+
error: "IssuerSignature must be populated"
|
|
299
269
|
}).refine((data) => data.recipientSignature !== "0x", {
|
|
300
|
-
|
|
301
|
-
}).refine(...
|
|
302
|
-
var
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
270
|
+
error: "RecipientSignature must be populated"
|
|
271
|
+
}).refine(...ExternalValidatorRefinement);
|
|
272
|
+
var safeParseAndThrowFormatted = (schema, data, message) => {
|
|
273
|
+
const result = schema.safeParse(data);
|
|
274
|
+
if (!result.success) {
|
|
275
|
+
throw new Error(`${message}: ${zod.z.prettifyError(result.error)}`, { cause: result.error });
|
|
276
|
+
}
|
|
277
|
+
return result.data;
|
|
278
|
+
};
|
|
279
|
+
var validateSelfPermitOptions = (options) => {
|
|
280
|
+
return safeParseAndThrowFormatted(SelfPermitOptionsValidator, options, "Invalid self permit options");
|
|
281
|
+
};
|
|
282
|
+
var validateSharingPermitOptions = (options) => {
|
|
283
|
+
return safeParseAndThrowFormatted(SharingPermitOptionsValidator, options, "Invalid sharing permit options");
|
|
284
|
+
};
|
|
285
|
+
var validateImportPermitOptions = (options) => {
|
|
286
|
+
return safeParseAndThrowFormatted(ImportPermitOptionsValidator, options, "Invalid import permit options");
|
|
287
|
+
};
|
|
288
|
+
var validateSelfPermit = (permit) => {
|
|
289
|
+
return safeParseAndThrowFormatted(SelfPermitValidator, permit, "Invalid self permit");
|
|
290
|
+
};
|
|
291
|
+
var validateSharingPermit = (permit) => {
|
|
292
|
+
return safeParseAndThrowFormatted(SharingPermitValidator, permit, "Invalid sharing permit");
|
|
293
|
+
};
|
|
294
|
+
var validateImportPermit = (permit) => {
|
|
295
|
+
return safeParseAndThrowFormatted(ImportPermitValidator, permit, "Invalid import permit");
|
|
296
|
+
};
|
|
308
297
|
var ValidationUtils = {
|
|
309
298
|
/**
|
|
310
299
|
* Check if permit is expired
|
|
@@ -399,75 +388,242 @@ var SignatureUtils = {
|
|
|
399
388
|
}
|
|
400
389
|
};
|
|
401
390
|
|
|
391
|
+
// core/consts.ts
|
|
392
|
+
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
393
|
+
|
|
394
|
+
// permits/onchain-utils.ts
|
|
395
|
+
var getAclAddress = async (publicClient) => {
|
|
396
|
+
const ACL_IFACE = "function acl() view returns (address)";
|
|
397
|
+
const aclAbi = viem.parseAbi([ACL_IFACE]);
|
|
398
|
+
return await publicClient.readContract({
|
|
399
|
+
address: TASK_MANAGER_ADDRESS,
|
|
400
|
+
abi: aclAbi,
|
|
401
|
+
functionName: "acl"
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
var getAclEIP712Domain = async (publicClient) => {
|
|
405
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
406
|
+
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
407
|
+
const domainAbi = viem.parseAbi([EIP712_DOMAIN_IFACE]);
|
|
408
|
+
const domain = await publicClient.readContract({
|
|
409
|
+
address: aclAddress,
|
|
410
|
+
abi: domainAbi,
|
|
411
|
+
functionName: "eip712Domain"
|
|
412
|
+
});
|
|
413
|
+
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
414
|
+
return {
|
|
415
|
+
name,
|
|
416
|
+
version,
|
|
417
|
+
chainId: Number(chainId),
|
|
418
|
+
verifyingContract
|
|
419
|
+
};
|
|
420
|
+
};
|
|
421
|
+
var checkPermitValidityOnChain = async (permission, publicClient) => {
|
|
422
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
423
|
+
try {
|
|
424
|
+
await publicClient.simulateContract({
|
|
425
|
+
address: aclAddress,
|
|
426
|
+
abi: checkPermitValidityAbi,
|
|
427
|
+
functionName: "checkPermitValidity",
|
|
428
|
+
args: [
|
|
429
|
+
{
|
|
430
|
+
issuer: permission.issuer,
|
|
431
|
+
expiration: BigInt(permission.expiration),
|
|
432
|
+
recipient: permission.recipient,
|
|
433
|
+
validatorId: BigInt(permission.validatorId),
|
|
434
|
+
validatorContract: permission.validatorContract,
|
|
435
|
+
sealingKey: permission.sealingKey,
|
|
436
|
+
issuerSignature: permission.issuerSignature,
|
|
437
|
+
recipientSignature: permission.recipientSignature
|
|
438
|
+
}
|
|
439
|
+
]
|
|
440
|
+
});
|
|
441
|
+
return true;
|
|
442
|
+
} catch (err) {
|
|
443
|
+
if (err instanceof viem.BaseError) {
|
|
444
|
+
const revertError = err.walk((err2) => err2 instanceof viem.ContractFunctionRevertedError);
|
|
445
|
+
if (revertError instanceof viem.ContractFunctionRevertedError) {
|
|
446
|
+
const errorName = revertError.data?.errorName ?? "";
|
|
447
|
+
throw new Error(errorName);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
const customErrorName = extractCustomErrorFromDetails(err, checkPermitValidityAbi);
|
|
451
|
+
if (customErrorName) {
|
|
452
|
+
throw new Error(customErrorName);
|
|
453
|
+
}
|
|
454
|
+
const hhDetailsData = extractReturnData(err);
|
|
455
|
+
if (hhDetailsData != null) {
|
|
456
|
+
const decoded = viem.decodeErrorResult({
|
|
457
|
+
abi: checkPermitValidityAbi,
|
|
458
|
+
data: hhDetailsData
|
|
459
|
+
});
|
|
460
|
+
throw new Error(decoded.errorName);
|
|
461
|
+
}
|
|
462
|
+
throw err;
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
function extractCustomErrorFromDetails(err, abi) {
|
|
466
|
+
const anyErr = err;
|
|
467
|
+
const details = anyErr?.details ?? anyErr?.cause?.details;
|
|
468
|
+
if (typeof details === "string") {
|
|
469
|
+
const customErrorMatch = details.match(/reverted with custom error '(\w+)\(\)'/);
|
|
470
|
+
if (customErrorMatch) {
|
|
471
|
+
const errorName = customErrorMatch[1];
|
|
472
|
+
const errorExists = abi.some((item) => item.type === "error" && item.name === errorName);
|
|
473
|
+
if (errorExists) {
|
|
474
|
+
return errorName;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return void 0;
|
|
479
|
+
}
|
|
480
|
+
function extractReturnData(err) {
|
|
481
|
+
const anyErr = err;
|
|
482
|
+
const s = anyErr?.details ?? anyErr?.cause?.details ?? anyErr?.shortMessage ?? anyErr?.message ?? String(err);
|
|
483
|
+
return s.match(/return data:\s*(0x[a-fA-F0-9]+)/)?.[1];
|
|
484
|
+
}
|
|
485
|
+
var checkPermitValidityAbi = [
|
|
486
|
+
{
|
|
487
|
+
type: "function",
|
|
488
|
+
name: "checkPermitValidity",
|
|
489
|
+
inputs: [
|
|
490
|
+
{
|
|
491
|
+
name: "permission",
|
|
492
|
+
type: "tuple",
|
|
493
|
+
internalType: "struct Permission",
|
|
494
|
+
components: [
|
|
495
|
+
{
|
|
496
|
+
name: "issuer",
|
|
497
|
+
type: "address",
|
|
498
|
+
internalType: "address"
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
name: "expiration",
|
|
502
|
+
type: "uint64",
|
|
503
|
+
internalType: "uint64"
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
name: "recipient",
|
|
507
|
+
type: "address",
|
|
508
|
+
internalType: "address"
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
name: "validatorId",
|
|
512
|
+
type: "uint256",
|
|
513
|
+
internalType: "uint256"
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
name: "validatorContract",
|
|
517
|
+
type: "address",
|
|
518
|
+
internalType: "address"
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
name: "sealingKey",
|
|
522
|
+
type: "bytes32",
|
|
523
|
+
internalType: "bytes32"
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
name: "issuerSignature",
|
|
527
|
+
type: "bytes",
|
|
528
|
+
internalType: "bytes"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "recipientSignature",
|
|
532
|
+
type: "bytes",
|
|
533
|
+
internalType: "bytes"
|
|
534
|
+
}
|
|
535
|
+
]
|
|
536
|
+
}
|
|
537
|
+
],
|
|
538
|
+
outputs: [
|
|
539
|
+
{
|
|
540
|
+
name: "",
|
|
541
|
+
type: "bool",
|
|
542
|
+
internalType: "bool"
|
|
543
|
+
}
|
|
544
|
+
],
|
|
545
|
+
stateMutability: "view"
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
type: "error",
|
|
549
|
+
name: "PermissionInvalid_Disabled",
|
|
550
|
+
inputs: []
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
type: "error",
|
|
554
|
+
name: "PermissionInvalid_Expired",
|
|
555
|
+
inputs: []
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
type: "error",
|
|
559
|
+
name: "PermissionInvalid_IssuerSignature",
|
|
560
|
+
inputs: []
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
type: "error",
|
|
564
|
+
name: "PermissionInvalid_RecipientSignature",
|
|
565
|
+
inputs: []
|
|
566
|
+
}
|
|
567
|
+
];
|
|
568
|
+
|
|
402
569
|
// permits/permit.ts
|
|
403
570
|
var PermitUtils = {
|
|
404
571
|
/**
|
|
405
572
|
* Create a self permit for personal use
|
|
406
573
|
*/
|
|
407
|
-
createSelf:
|
|
574
|
+
createSelf: (options) => {
|
|
408
575
|
const validation = validateSelfPermitOptions(options);
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
const sealingPair = await GenerateSealingKey();
|
|
415
|
-
return {
|
|
416
|
-
...validation.data,
|
|
576
|
+
const sealingPair = GenerateSealingKey();
|
|
577
|
+
const permit = {
|
|
578
|
+
hash: PermitUtils.getHash(validation),
|
|
579
|
+
...validation,
|
|
417
580
|
sealingPair,
|
|
418
581
|
_signedDomain: void 0
|
|
419
582
|
};
|
|
583
|
+
return permit;
|
|
420
584
|
},
|
|
421
585
|
/**
|
|
422
586
|
* Create a sharing permit to be shared with another user
|
|
423
587
|
*/
|
|
424
|
-
createSharing:
|
|
588
|
+
createSharing: (options) => {
|
|
425
589
|
const validation = validateSharingPermitOptions(options);
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
}
|
|
431
|
-
const sealingPair = await GenerateSealingKey();
|
|
432
|
-
return {
|
|
433
|
-
...validation.data,
|
|
590
|
+
const sealingPair = GenerateSealingKey();
|
|
591
|
+
const permit = {
|
|
592
|
+
hash: PermitUtils.getHash(validation),
|
|
593
|
+
...validation,
|
|
434
594
|
sealingPair,
|
|
435
595
|
_signedDomain: void 0
|
|
436
596
|
};
|
|
597
|
+
return permit;
|
|
437
598
|
},
|
|
438
599
|
/**
|
|
439
600
|
* Import a shared permit from various input formats
|
|
440
601
|
*/
|
|
441
|
-
importShared:
|
|
602
|
+
importShared: (options) => {
|
|
442
603
|
let parsedOptions;
|
|
443
604
|
if (typeof options === "string") {
|
|
444
605
|
try {
|
|
445
606
|
parsedOptions = JSON.parse(options);
|
|
446
607
|
} catch (error) {
|
|
447
|
-
throw new Error(`
|
|
608
|
+
throw new Error(`Failed to parse JSON string: ${error}`);
|
|
448
609
|
}
|
|
449
610
|
} else if (typeof options === "object" && options !== null) {
|
|
450
611
|
parsedOptions = options;
|
|
451
612
|
} else {
|
|
452
|
-
throw new Error(
|
|
453
|
-
"PermitUtils :: importShared :: Invalid input type, expected ImportSharedPermitOptions, object, or string"
|
|
454
|
-
);
|
|
613
|
+
throw new Error("Invalid input type, expected ImportSharedPermitOptions, object, or string");
|
|
455
614
|
}
|
|
456
615
|
if (parsedOptions.type != null && parsedOptions.type !== "sharing") {
|
|
457
|
-
throw new Error(`
|
|
616
|
+
throw new Error(`Invalid permit type <${parsedOptions.type}>, must be "sharing"`);
|
|
458
617
|
}
|
|
459
618
|
const validation = validateImportPermitOptions({ ...parsedOptions, type: "recipient" });
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
const sealingPair = await GenerateSealingKey();
|
|
466
|
-
return {
|
|
467
|
-
...validation.data,
|
|
619
|
+
const sealingPair = GenerateSealingKey();
|
|
620
|
+
const permit = {
|
|
621
|
+
hash: PermitUtils.getHash(validation),
|
|
622
|
+
...validation,
|
|
468
623
|
sealingPair,
|
|
469
624
|
_signedDomain: void 0
|
|
470
625
|
};
|
|
626
|
+
return permit;
|
|
471
627
|
},
|
|
472
628
|
/**
|
|
473
629
|
* Sign a permit with the provided wallet client
|
|
@@ -475,11 +631,11 @@ var PermitUtils = {
|
|
|
475
631
|
sign: async (permit, publicClient, walletClient) => {
|
|
476
632
|
if (walletClient == null || walletClient.account == null) {
|
|
477
633
|
throw new Error(
|
|
478
|
-
"
|
|
634
|
+
"Missing walletClient, you must pass in a `walletClient` for the connected user to create a permit signature"
|
|
479
635
|
);
|
|
480
636
|
}
|
|
481
637
|
const primaryType = SignatureUtils.getPrimaryType(permit.type);
|
|
482
|
-
const domain = await
|
|
638
|
+
const domain = await getAclEIP712Domain(publicClient);
|
|
483
639
|
const { types, message } = SignatureUtils.getSignatureParams(PermitUtils.getPermission(permit, true), primaryType);
|
|
484
640
|
const signature = await walletClient.signTypedData({
|
|
485
641
|
domain,
|
|
@@ -508,21 +664,21 @@ var PermitUtils = {
|
|
|
508
664
|
* Create and sign a self permit in one operation
|
|
509
665
|
*/
|
|
510
666
|
createSelfAndSign: async (options, publicClient, walletClient) => {
|
|
511
|
-
const permit =
|
|
667
|
+
const permit = PermitUtils.createSelf(options);
|
|
512
668
|
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
513
669
|
},
|
|
514
670
|
/**
|
|
515
671
|
* Create and sign a sharing permit in one operation
|
|
516
672
|
*/
|
|
517
673
|
createSharingAndSign: async (options, publicClient, walletClient) => {
|
|
518
|
-
const permit =
|
|
674
|
+
const permit = PermitUtils.createSharing(options);
|
|
519
675
|
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
520
676
|
},
|
|
521
677
|
/**
|
|
522
678
|
* Import and sign a shared permit in one operation from various input formats
|
|
523
679
|
*/
|
|
524
680
|
importSharedAndSign: async (options, publicClient, walletClient) => {
|
|
525
|
-
const permit =
|
|
681
|
+
const permit = PermitUtils.importShared(options);
|
|
526
682
|
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
527
683
|
},
|
|
528
684
|
/**
|
|
@@ -539,6 +695,7 @@ var PermitUtils = {
|
|
|
539
695
|
*/
|
|
540
696
|
serialize: (permit) => {
|
|
541
697
|
return {
|
|
698
|
+
hash: permit.hash,
|
|
542
699
|
name: permit.name,
|
|
543
700
|
type: permit.type,
|
|
544
701
|
issuer: permit.issuer,
|
|
@@ -563,7 +720,7 @@ var PermitUtils = {
|
|
|
563
720
|
} else if (permit.type === "recipient") {
|
|
564
721
|
return validateImportPermit(permit);
|
|
565
722
|
} else {
|
|
566
|
-
throw new Error("
|
|
723
|
+
throw new Error("Invalid permit type");
|
|
567
724
|
}
|
|
568
725
|
},
|
|
569
726
|
/**
|
|
@@ -571,12 +728,7 @@ var PermitUtils = {
|
|
|
571
728
|
*/
|
|
572
729
|
getPermission: (permit, skipValidation = false) => {
|
|
573
730
|
if (!skipValidation) {
|
|
574
|
-
|
|
575
|
-
if (!validationResult.success) {
|
|
576
|
-
throw new Error(
|
|
577
|
-
`PermitUtils :: getPermission :: permit validation failed - ${JSON.stringify(validationResult.error, null, 2)} ${JSON.stringify(permit, null, 2)}`
|
|
578
|
-
);
|
|
579
|
-
}
|
|
731
|
+
PermitUtils.validate(permit);
|
|
580
732
|
}
|
|
581
733
|
return {
|
|
582
734
|
issuer: permit.issuer,
|
|
@@ -657,28 +809,7 @@ var PermitUtils = {
|
|
|
657
809
|
* Fetch EIP712 domain from the blockchain
|
|
658
810
|
*/
|
|
659
811
|
fetchEIP712Domain: async (publicClient) => {
|
|
660
|
-
|
|
661
|
-
const ACL_IFACE = "function acl() view returns (address)";
|
|
662
|
-
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
663
|
-
const aclAbi = viem.parseAbi([ACL_IFACE]);
|
|
664
|
-
const aclAddress = await publicClient.readContract({
|
|
665
|
-
address: TASK_MANAGER_ADDRESS,
|
|
666
|
-
abi: aclAbi,
|
|
667
|
-
functionName: "acl"
|
|
668
|
-
});
|
|
669
|
-
const domainAbi = viem.parseAbi([EIP712_DOMAIN_IFACE]);
|
|
670
|
-
const domain = await publicClient.readContract({
|
|
671
|
-
address: aclAddress,
|
|
672
|
-
abi: domainAbi,
|
|
673
|
-
functionName: "eip712Domain"
|
|
674
|
-
});
|
|
675
|
-
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
676
|
-
return {
|
|
677
|
-
name,
|
|
678
|
-
version,
|
|
679
|
-
chainId: Number(chainId),
|
|
680
|
-
verifyingContract
|
|
681
|
-
};
|
|
812
|
+
return getAclEIP712Domain(publicClient);
|
|
682
813
|
},
|
|
683
814
|
/**
|
|
684
815
|
* Check if permit's signed domain matches the provided domain
|
|
@@ -692,18 +823,23 @@ var PermitUtils = {
|
|
|
692
823
|
checkSignedDomainValid: async (permit, publicClient) => {
|
|
693
824
|
if (permit._signedDomain == null)
|
|
694
825
|
return false;
|
|
695
|
-
const domain = await
|
|
826
|
+
const domain = await getAclEIP712Domain(publicClient);
|
|
696
827
|
return PermitUtils.matchesDomain(permit, domain);
|
|
828
|
+
},
|
|
829
|
+
/**
|
|
830
|
+
* Check if permit passes the on-chain validation
|
|
831
|
+
*/
|
|
832
|
+
checkValidityOnChain: async (permit, publicClient) => {
|
|
833
|
+
const permission = PermitUtils.getPermission(permit);
|
|
834
|
+
return checkPermitValidityOnChain(permission, publicClient);
|
|
697
835
|
}
|
|
698
836
|
};
|
|
837
|
+
var PERMIT_STORE_DEFAULTS = {
|
|
838
|
+
permits: {},
|
|
839
|
+
activePermitHash: {}
|
|
840
|
+
};
|
|
699
841
|
var _permitStore = vanilla.createStore()(
|
|
700
|
-
middleware.persist(
|
|
701
|
-
() => ({
|
|
702
|
-
permits: {},
|
|
703
|
-
activePermitHash: {}
|
|
704
|
-
}),
|
|
705
|
-
{ name: "cofhesdk-permits" }
|
|
706
|
-
)
|
|
842
|
+
middleware.persist(() => PERMIT_STORE_DEFAULTS, { name: "cofhesdk-permits" })
|
|
707
843
|
);
|
|
708
844
|
var clearStaleStore = () => {
|
|
709
845
|
const state = _permitStore.getState();
|
|
@@ -749,11 +885,11 @@ var setPermit = (chainId, account, permit) => {
|
|
|
749
885
|
state.permits[chainId] = {};
|
|
750
886
|
if (state.permits[chainId][account] == null)
|
|
751
887
|
state.permits[chainId][account] = {};
|
|
752
|
-
state.permits[chainId][account][
|
|
888
|
+
state.permits[chainId][account][permit.hash] = PermitUtils.serialize(permit);
|
|
753
889
|
})
|
|
754
890
|
);
|
|
755
891
|
};
|
|
756
|
-
var removePermit = (chainId, account, hash
|
|
892
|
+
var removePermit = (chainId, account, hash) => {
|
|
757
893
|
clearStaleStore();
|
|
758
894
|
_permitStore.setState(
|
|
759
895
|
immer.produce((state) => {
|
|
@@ -767,15 +903,7 @@ var removePermit = (chainId, account, hash, force) => {
|
|
|
767
903
|
if (accountPermits[hash] == null)
|
|
768
904
|
return;
|
|
769
905
|
if (state.activePermitHash[chainId][account] === hash) {
|
|
770
|
-
|
|
771
|
-
if (otherPermitHash) {
|
|
772
|
-
state.activePermitHash[chainId][account] = otherPermitHash;
|
|
773
|
-
} else {
|
|
774
|
-
if (!force) {
|
|
775
|
-
throw new Error("Cannot remove the last permit without force flag");
|
|
776
|
-
}
|
|
777
|
-
state.activePermitHash[chainId][account] = void 0;
|
|
778
|
-
}
|
|
906
|
+
state.activePermitHash[chainId][account] = void 0;
|
|
779
907
|
}
|
|
780
908
|
accountPermits[hash] = void 0;
|
|
781
909
|
})
|
|
@@ -826,6 +954,7 @@ var permitStore = {
|
|
|
826
954
|
exports.GenerateSealingKey = GenerateSealingKey;
|
|
827
955
|
exports.ImportPermitOptionsValidator = ImportPermitOptionsValidator;
|
|
828
956
|
exports.ImportPermitValidator = ImportPermitValidator;
|
|
957
|
+
exports.PERMIT_STORE_DEFAULTS = PERMIT_STORE_DEFAULTS;
|
|
829
958
|
exports.PermitUtils = PermitUtils;
|
|
830
959
|
exports.SealingKey = SealingKey;
|
|
831
960
|
exports.SelfPermitOptionsValidator = SelfPermitOptionsValidator;
|
|
@@ -836,6 +965,10 @@ exports.SignatureTypes = SignatureTypes;
|
|
|
836
965
|
exports.SignatureUtils = SignatureUtils;
|
|
837
966
|
exports.ValidationUtils = ValidationUtils;
|
|
838
967
|
exports._permitStore = _permitStore;
|
|
968
|
+
exports.addressNotZeroSchema = addressNotZeroSchema;
|
|
969
|
+
exports.addressSchema = addressSchema;
|
|
970
|
+
exports.bytesNotEmptySchema = bytesNotEmptySchema;
|
|
971
|
+
exports.bytesSchema = bytesSchema;
|
|
839
972
|
exports.clearStaleStore = clearStaleStore;
|
|
840
973
|
exports.getActivePermit = getActivePermit;
|
|
841
974
|
exports.getActivePermitHash = getActivePermitHash;
|