@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isAddress, zeroAddress, keccak256, toHex, parseAbi } from 'viem';
|
|
1
|
+
import { isAddress, getAddress, zeroAddress, isHex, keccak256, toHex, parseAbi, BaseError, ContractFunctionRevertedError, decodeErrorResult } from 'viem';
|
|
2
2
|
import * as nacl from 'tweetnacl';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { createStore } from 'zustand/vanilla';
|
|
@@ -54,9 +54,6 @@ function isBigIntOrNumber(value) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
function is0xPrefixed(value) {
|
|
58
|
-
return value.startsWith("0x");
|
|
59
|
-
}
|
|
60
57
|
|
|
61
58
|
// permits/sealing.ts
|
|
62
59
|
var PRIVATE_KEY_LENGTH = 64;
|
|
@@ -136,7 +133,7 @@ var SealingKey = class _SealingKey {
|
|
|
136
133
|
};
|
|
137
134
|
};
|
|
138
135
|
};
|
|
139
|
-
var GenerateSealingKey =
|
|
136
|
+
var GenerateSealingKey = () => {
|
|
140
137
|
const sodiumKeypair = nacl.box.keyPair();
|
|
141
138
|
return new SealingKey(toHexString(sodiumKeypair.secretKey), toHexString(sodiumKeypair.publicKey));
|
|
142
139
|
};
|
|
@@ -144,145 +141,137 @@ var SerializedSealingPair = z.object({
|
|
|
144
141
|
privateKey: z.string(),
|
|
145
142
|
publicKey: z.string()
|
|
146
143
|
});
|
|
144
|
+
var addressSchema = z.string().refine((val) => isAddress(val), {
|
|
145
|
+
error: "Invalid address"
|
|
146
|
+
}).transform((val) => getAddress(val));
|
|
147
|
+
var addressNotZeroSchema = addressSchema.refine((val) => val !== zeroAddress, {
|
|
148
|
+
error: "Must not be zeroAddress"
|
|
149
|
+
});
|
|
150
|
+
var bytesSchema = z.custom(
|
|
151
|
+
(val) => {
|
|
152
|
+
return typeof val === "string" && isHex(val);
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
message: "Invalid hex value"
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
var bytesNotEmptySchema = bytesSchema.refine((val) => val !== "0x", {
|
|
159
|
+
error: "Must not be empty"
|
|
160
|
+
});
|
|
161
|
+
var DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1e3) + 7 * 24 * 60 * 60;
|
|
147
162
|
var zPermitWithDefaults = z.object({
|
|
148
163
|
name: z.string().optional().default("Unnamed Permit"),
|
|
149
164
|
type: z.enum(["self", "sharing", "recipient"]),
|
|
150
|
-
issuer:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
message: "Permit recipient :: invalid address"
|
|
158
|
-
}),
|
|
159
|
-
validatorId: z.number().optional().default(0),
|
|
160
|
-
validatorContract: z.string().optional().default(zeroAddress).refine((val) => isAddress(val), {
|
|
161
|
-
message: "Permit validatorContract :: invalid address"
|
|
162
|
-
}),
|
|
163
|
-
issuerSignature: z.string().optional().default("0x"),
|
|
164
|
-
recipientSignature: z.string().optional().default("0x")
|
|
165
|
+
issuer: addressNotZeroSchema,
|
|
166
|
+
expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
167
|
+
recipient: addressSchema.optional().default(zeroAddress),
|
|
168
|
+
validatorId: z.int().optional().default(0),
|
|
169
|
+
validatorContract: addressSchema.optional().default(zeroAddress),
|
|
170
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
171
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
165
172
|
});
|
|
166
173
|
var zPermitWithSealingPair = zPermitWithDefaults.extend({
|
|
167
174
|
sealingPair: SerializedSealingPair.optional()
|
|
168
175
|
});
|
|
169
|
-
var
|
|
176
|
+
var ExternalValidatorRefinement = [
|
|
170
177
|
(data) => data.validatorId !== 0 && data.validatorContract !== zeroAddress || data.validatorId === 0 && data.validatorContract === zeroAddress,
|
|
171
178
|
{
|
|
172
|
-
|
|
179
|
+
error: "Permit external validator :: validatorId and validatorContract must either both be set or both be unset.",
|
|
173
180
|
path: ["validatorId", "validatorContract"]
|
|
174
181
|
}
|
|
175
182
|
];
|
|
183
|
+
var RecipientRefinement = [
|
|
184
|
+
(data) => data.issuer !== data.recipient,
|
|
185
|
+
{
|
|
186
|
+
error: "Sharing permit :: issuer and recipient must not be the same",
|
|
187
|
+
path: ["issuer", "recipient"]
|
|
188
|
+
}
|
|
189
|
+
];
|
|
176
190
|
var SelfPermitOptionsValidator = z.object({
|
|
177
191
|
type: z.literal("self").optional().default("self"),
|
|
178
|
-
issuer:
|
|
179
|
-
message: "Self permit issuer :: invalid address"
|
|
180
|
-
}).refine((val) => val !== zeroAddress, {
|
|
181
|
-
message: "Self permit issuer :: must not be zeroAddress"
|
|
182
|
-
}),
|
|
192
|
+
issuer: addressNotZeroSchema,
|
|
183
193
|
name: z.string().optional().default("Unnamed Permit"),
|
|
184
|
-
expiration: z.
|
|
185
|
-
recipient:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
validatorContract: z.string().optional().default(zeroAddress).refine((val) => isAddress(val), {
|
|
192
|
-
message: "Self permit validatorContract :: invalid address"
|
|
193
|
-
}),
|
|
194
|
-
issuerSignature: z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
195
|
-
message: "Self permit issuerSignature :: must be 0x prefixed"
|
|
196
|
-
}),
|
|
197
|
-
recipientSignature: z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
198
|
-
message: "Self permit recipientSignature :: must be 0x prefixed"
|
|
199
|
-
})
|
|
200
|
-
}).refine(...ValidatorContractRefinement);
|
|
194
|
+
expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
195
|
+
recipient: addressSchema.optional().default(zeroAddress),
|
|
196
|
+
validatorId: z.int().optional().default(0),
|
|
197
|
+
validatorContract: addressSchema.optional().default(zeroAddress),
|
|
198
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
199
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
200
|
+
}).refine(...ExternalValidatorRefinement);
|
|
201
201
|
var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "self", {
|
|
202
|
-
|
|
202
|
+
error: "Type must be 'self'"
|
|
203
203
|
}).refine((data) => data.recipient === zeroAddress, {
|
|
204
|
-
|
|
204
|
+
error: "Recipient must be zeroAddress"
|
|
205
205
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
206
|
-
|
|
206
|
+
error: "IssuerSignature must be populated"
|
|
207
207
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
208
|
-
|
|
209
|
-
}).refine(...
|
|
208
|
+
error: "RecipientSignature must be empty"
|
|
209
|
+
}).refine(...ExternalValidatorRefinement);
|
|
210
210
|
var SharingPermitOptionsValidator = z.object({
|
|
211
211
|
type: z.literal("sharing").optional().default("sharing"),
|
|
212
|
-
issuer:
|
|
213
|
-
|
|
214
|
-
}).refine((val) => val !== zeroAddress, {
|
|
215
|
-
message: "Sharing permit issuer :: must not be zeroAddress"
|
|
216
|
-
}),
|
|
217
|
-
recipient: z.string().refine((val) => isAddress(val), {
|
|
218
|
-
message: "Sharing permit recipient :: invalid address"
|
|
219
|
-
}).refine((val) => val !== zeroAddress, {
|
|
220
|
-
message: "Sharing permit recipient :: must not be zeroAddress"
|
|
221
|
-
}),
|
|
212
|
+
issuer: addressNotZeroSchema,
|
|
213
|
+
recipient: addressNotZeroSchema,
|
|
222
214
|
name: z.string().optional().default("Unnamed Permit"),
|
|
223
|
-
expiration: z.
|
|
224
|
-
validatorId: z.
|
|
225
|
-
validatorContract:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
message: "Sharing permit issuerSignature :: must be 0x prefixed"
|
|
230
|
-
}),
|
|
231
|
-
recipientSignature: z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
232
|
-
message: "Sharing permit recipientSignature :: must be 0x prefixed"
|
|
233
|
-
})
|
|
234
|
-
}).refine(...ValidatorContractRefinement);
|
|
215
|
+
expiration: z.int().optional().default(DEFAULT_EXPIRATION_FN),
|
|
216
|
+
validatorId: z.int().optional().default(0),
|
|
217
|
+
validatorContract: addressSchema.optional().default(zeroAddress),
|
|
218
|
+
issuerSignature: bytesSchema.optional().default("0x"),
|
|
219
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
220
|
+
}).refine(...RecipientRefinement).refine(...ExternalValidatorRefinement);
|
|
235
221
|
var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "sharing", {
|
|
236
|
-
|
|
222
|
+
error: "Type must be 'sharing'"
|
|
237
223
|
}).refine((data) => data.recipient !== zeroAddress, {
|
|
238
|
-
|
|
224
|
+
error: "Recipient must not be zeroAddress"
|
|
239
225
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
240
|
-
|
|
226
|
+
error: "IssuerSignature must be populated"
|
|
241
227
|
}).refine((data) => data.recipientSignature === "0x", {
|
|
242
|
-
|
|
243
|
-
}).refine(...
|
|
228
|
+
error: "RecipientSignature must be empty"
|
|
229
|
+
}).refine(...ExternalValidatorRefinement);
|
|
244
230
|
var ImportPermitOptionsValidator = z.object({
|
|
245
231
|
type: z.literal("recipient").optional().default("recipient"),
|
|
246
|
-
issuer:
|
|
247
|
-
|
|
248
|
-
}).refine((val) => val !== zeroAddress, {
|
|
249
|
-
message: "Import permit issuer :: must not be zeroAddress"
|
|
250
|
-
}),
|
|
251
|
-
recipient: z.string().refine((val) => isAddress(val), {
|
|
252
|
-
message: "Import permit recipient :: invalid address"
|
|
253
|
-
}).refine((val) => val !== zeroAddress, {
|
|
254
|
-
message: "Import permit recipient :: must not be zeroAddress"
|
|
255
|
-
}),
|
|
256
|
-
issuerSignature: z.string().refine((val) => is0xPrefixed(val), {
|
|
257
|
-
message: "Import permit issuerSignature :: must be 0x prefixed"
|
|
258
|
-
}).refine((val) => val !== "0x", {
|
|
259
|
-
message: "Import permit :: issuerSignature must be provided"
|
|
260
|
-
}),
|
|
232
|
+
issuer: addressNotZeroSchema,
|
|
233
|
+
recipient: addressNotZeroSchema,
|
|
261
234
|
name: z.string().optional().default("Unnamed Permit"),
|
|
262
|
-
expiration: z.
|
|
263
|
-
validatorId: z.
|
|
264
|
-
validatorContract:
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
message: "Import permit recipientSignature :: must be 0x prefixed"
|
|
269
|
-
})
|
|
270
|
-
}).refine(...ValidatorContractRefinement);
|
|
235
|
+
expiration: z.int(),
|
|
236
|
+
validatorId: z.int().optional().default(0),
|
|
237
|
+
validatorContract: addressSchema.optional().default(zeroAddress),
|
|
238
|
+
issuerSignature: bytesNotEmptySchema,
|
|
239
|
+
recipientSignature: bytesSchema.optional().default("0x")
|
|
240
|
+
}).refine(...ExternalValidatorRefinement);
|
|
271
241
|
var ImportPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "recipient", {
|
|
272
|
-
|
|
242
|
+
error: "Type must be 'recipient'"
|
|
273
243
|
}).refine((data) => data.recipient !== zeroAddress, {
|
|
274
|
-
|
|
244
|
+
error: "Recipient must not be zeroAddress"
|
|
275
245
|
}).refine((data) => data.issuerSignature !== "0x", {
|
|
276
|
-
|
|
246
|
+
error: "IssuerSignature must be populated"
|
|
277
247
|
}).refine((data) => data.recipientSignature !== "0x", {
|
|
278
|
-
|
|
279
|
-
}).refine(...
|
|
280
|
-
var
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
248
|
+
error: "RecipientSignature must be populated"
|
|
249
|
+
}).refine(...ExternalValidatorRefinement);
|
|
250
|
+
var safeParseAndThrowFormatted = (schema, data, message) => {
|
|
251
|
+
const result = schema.safeParse(data);
|
|
252
|
+
if (!result.success) {
|
|
253
|
+
throw new Error(`${message}: ${z.prettifyError(result.error)}`, { cause: result.error });
|
|
254
|
+
}
|
|
255
|
+
return result.data;
|
|
256
|
+
};
|
|
257
|
+
var validateSelfPermitOptions = (options) => {
|
|
258
|
+
return safeParseAndThrowFormatted(SelfPermitOptionsValidator, options, "Invalid self permit options");
|
|
259
|
+
};
|
|
260
|
+
var validateSharingPermitOptions = (options) => {
|
|
261
|
+
return safeParseAndThrowFormatted(SharingPermitOptionsValidator, options, "Invalid sharing permit options");
|
|
262
|
+
};
|
|
263
|
+
var validateImportPermitOptions = (options) => {
|
|
264
|
+
return safeParseAndThrowFormatted(ImportPermitOptionsValidator, options, "Invalid import permit options");
|
|
265
|
+
};
|
|
266
|
+
var validateSelfPermit = (permit) => {
|
|
267
|
+
return safeParseAndThrowFormatted(SelfPermitValidator, permit, "Invalid self permit");
|
|
268
|
+
};
|
|
269
|
+
var validateSharingPermit = (permit) => {
|
|
270
|
+
return safeParseAndThrowFormatted(SharingPermitValidator, permit, "Invalid sharing permit");
|
|
271
|
+
};
|
|
272
|
+
var validateImportPermit = (permit) => {
|
|
273
|
+
return safeParseAndThrowFormatted(ImportPermitValidator, permit, "Invalid import permit");
|
|
274
|
+
};
|
|
286
275
|
var ValidationUtils = {
|
|
287
276
|
/**
|
|
288
277
|
* Check if permit is expired
|
|
@@ -377,75 +366,247 @@ var SignatureUtils = {
|
|
|
377
366
|
}
|
|
378
367
|
};
|
|
379
368
|
|
|
369
|
+
// core/consts.ts
|
|
370
|
+
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
371
|
+
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
372
|
+
var MOCKS_QUERY_DECRYPTER_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
373
|
+
var TEST_BED_ADDRESS = "0x0000000000000000000000000000000000005003";
|
|
374
|
+
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
375
|
+
var MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = "0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2";
|
|
376
|
+
|
|
377
|
+
// permits/onchain-utils.ts
|
|
378
|
+
var getAclAddress = async (publicClient) => {
|
|
379
|
+
const ACL_IFACE = "function acl() view returns (address)";
|
|
380
|
+
const aclAbi = parseAbi([ACL_IFACE]);
|
|
381
|
+
return await publicClient.readContract({
|
|
382
|
+
address: TASK_MANAGER_ADDRESS,
|
|
383
|
+
abi: aclAbi,
|
|
384
|
+
functionName: "acl"
|
|
385
|
+
});
|
|
386
|
+
};
|
|
387
|
+
var getAclEIP712Domain = async (publicClient) => {
|
|
388
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
389
|
+
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
390
|
+
const domainAbi = parseAbi([EIP712_DOMAIN_IFACE]);
|
|
391
|
+
const domain = await publicClient.readContract({
|
|
392
|
+
address: aclAddress,
|
|
393
|
+
abi: domainAbi,
|
|
394
|
+
functionName: "eip712Domain"
|
|
395
|
+
});
|
|
396
|
+
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
397
|
+
return {
|
|
398
|
+
name,
|
|
399
|
+
version,
|
|
400
|
+
chainId: Number(chainId),
|
|
401
|
+
verifyingContract
|
|
402
|
+
};
|
|
403
|
+
};
|
|
404
|
+
var checkPermitValidityOnChain = async (permission, publicClient) => {
|
|
405
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
406
|
+
try {
|
|
407
|
+
await publicClient.simulateContract({
|
|
408
|
+
address: aclAddress,
|
|
409
|
+
abi: checkPermitValidityAbi,
|
|
410
|
+
functionName: "checkPermitValidity",
|
|
411
|
+
args: [
|
|
412
|
+
{
|
|
413
|
+
issuer: permission.issuer,
|
|
414
|
+
expiration: BigInt(permission.expiration),
|
|
415
|
+
recipient: permission.recipient,
|
|
416
|
+
validatorId: BigInt(permission.validatorId),
|
|
417
|
+
validatorContract: permission.validatorContract,
|
|
418
|
+
sealingKey: permission.sealingKey,
|
|
419
|
+
issuerSignature: permission.issuerSignature,
|
|
420
|
+
recipientSignature: permission.recipientSignature
|
|
421
|
+
}
|
|
422
|
+
]
|
|
423
|
+
});
|
|
424
|
+
return true;
|
|
425
|
+
} catch (err) {
|
|
426
|
+
if (err instanceof BaseError) {
|
|
427
|
+
const revertError = err.walk((err2) => err2 instanceof ContractFunctionRevertedError);
|
|
428
|
+
if (revertError instanceof ContractFunctionRevertedError) {
|
|
429
|
+
const errorName = revertError.data?.errorName ?? "";
|
|
430
|
+
throw new Error(errorName);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
const customErrorName = extractCustomErrorFromDetails(err, checkPermitValidityAbi);
|
|
434
|
+
if (customErrorName) {
|
|
435
|
+
throw new Error(customErrorName);
|
|
436
|
+
}
|
|
437
|
+
const hhDetailsData = extractReturnData(err);
|
|
438
|
+
if (hhDetailsData != null) {
|
|
439
|
+
const decoded = decodeErrorResult({
|
|
440
|
+
abi: checkPermitValidityAbi,
|
|
441
|
+
data: hhDetailsData
|
|
442
|
+
});
|
|
443
|
+
throw new Error(decoded.errorName);
|
|
444
|
+
}
|
|
445
|
+
throw err;
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
function extractCustomErrorFromDetails(err, abi) {
|
|
449
|
+
const anyErr = err;
|
|
450
|
+
const details = anyErr?.details ?? anyErr?.cause?.details;
|
|
451
|
+
if (typeof details === "string") {
|
|
452
|
+
const customErrorMatch = details.match(/reverted with custom error '(\w+)\(\)'/);
|
|
453
|
+
if (customErrorMatch) {
|
|
454
|
+
const errorName = customErrorMatch[1];
|
|
455
|
+
const errorExists = abi.some((item) => item.type === "error" && item.name === errorName);
|
|
456
|
+
if (errorExists) {
|
|
457
|
+
return errorName;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return void 0;
|
|
462
|
+
}
|
|
463
|
+
function extractReturnData(err) {
|
|
464
|
+
const anyErr = err;
|
|
465
|
+
const s = anyErr?.details ?? anyErr?.cause?.details ?? anyErr?.shortMessage ?? anyErr?.message ?? String(err);
|
|
466
|
+
return s.match(/return data:\s*(0x[a-fA-F0-9]+)/)?.[1];
|
|
467
|
+
}
|
|
468
|
+
var checkPermitValidityAbi = [
|
|
469
|
+
{
|
|
470
|
+
type: "function",
|
|
471
|
+
name: "checkPermitValidity",
|
|
472
|
+
inputs: [
|
|
473
|
+
{
|
|
474
|
+
name: "permission",
|
|
475
|
+
type: "tuple",
|
|
476
|
+
internalType: "struct Permission",
|
|
477
|
+
components: [
|
|
478
|
+
{
|
|
479
|
+
name: "issuer",
|
|
480
|
+
type: "address",
|
|
481
|
+
internalType: "address"
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
name: "expiration",
|
|
485
|
+
type: "uint64",
|
|
486
|
+
internalType: "uint64"
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
name: "recipient",
|
|
490
|
+
type: "address",
|
|
491
|
+
internalType: "address"
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
name: "validatorId",
|
|
495
|
+
type: "uint256",
|
|
496
|
+
internalType: "uint256"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
name: "validatorContract",
|
|
500
|
+
type: "address",
|
|
501
|
+
internalType: "address"
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
name: "sealingKey",
|
|
505
|
+
type: "bytes32",
|
|
506
|
+
internalType: "bytes32"
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
name: "issuerSignature",
|
|
510
|
+
type: "bytes",
|
|
511
|
+
internalType: "bytes"
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
name: "recipientSignature",
|
|
515
|
+
type: "bytes",
|
|
516
|
+
internalType: "bytes"
|
|
517
|
+
}
|
|
518
|
+
]
|
|
519
|
+
}
|
|
520
|
+
],
|
|
521
|
+
outputs: [
|
|
522
|
+
{
|
|
523
|
+
name: "",
|
|
524
|
+
type: "bool",
|
|
525
|
+
internalType: "bool"
|
|
526
|
+
}
|
|
527
|
+
],
|
|
528
|
+
stateMutability: "view"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
type: "error",
|
|
532
|
+
name: "PermissionInvalid_Disabled",
|
|
533
|
+
inputs: []
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
type: "error",
|
|
537
|
+
name: "PermissionInvalid_Expired",
|
|
538
|
+
inputs: []
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
type: "error",
|
|
542
|
+
name: "PermissionInvalid_IssuerSignature",
|
|
543
|
+
inputs: []
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
type: "error",
|
|
547
|
+
name: "PermissionInvalid_RecipientSignature",
|
|
548
|
+
inputs: []
|
|
549
|
+
}
|
|
550
|
+
];
|
|
551
|
+
|
|
380
552
|
// permits/permit.ts
|
|
381
553
|
var PermitUtils = {
|
|
382
554
|
/**
|
|
383
555
|
* Create a self permit for personal use
|
|
384
556
|
*/
|
|
385
|
-
createSelf:
|
|
557
|
+
createSelf: (options) => {
|
|
386
558
|
const validation = validateSelfPermitOptions(options);
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
392
|
-
const sealingPair = await GenerateSealingKey();
|
|
393
|
-
return {
|
|
394
|
-
...validation.data,
|
|
559
|
+
const sealingPair = GenerateSealingKey();
|
|
560
|
+
const permit = {
|
|
561
|
+
hash: PermitUtils.getHash(validation),
|
|
562
|
+
...validation,
|
|
395
563
|
sealingPair,
|
|
396
564
|
_signedDomain: void 0
|
|
397
565
|
};
|
|
566
|
+
return permit;
|
|
398
567
|
},
|
|
399
568
|
/**
|
|
400
569
|
* Create a sharing permit to be shared with another user
|
|
401
570
|
*/
|
|
402
|
-
createSharing:
|
|
571
|
+
createSharing: (options) => {
|
|
403
572
|
const validation = validateSharingPermitOptions(options);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
const sealingPair = await GenerateSealingKey();
|
|
410
|
-
return {
|
|
411
|
-
...validation.data,
|
|
573
|
+
const sealingPair = GenerateSealingKey();
|
|
574
|
+
const permit = {
|
|
575
|
+
hash: PermitUtils.getHash(validation),
|
|
576
|
+
...validation,
|
|
412
577
|
sealingPair,
|
|
413
578
|
_signedDomain: void 0
|
|
414
579
|
};
|
|
580
|
+
return permit;
|
|
415
581
|
},
|
|
416
582
|
/**
|
|
417
583
|
* Import a shared permit from various input formats
|
|
418
584
|
*/
|
|
419
|
-
importShared:
|
|
585
|
+
importShared: (options) => {
|
|
420
586
|
let parsedOptions;
|
|
421
587
|
if (typeof options === "string") {
|
|
422
588
|
try {
|
|
423
589
|
parsedOptions = JSON.parse(options);
|
|
424
590
|
} catch (error) {
|
|
425
|
-
throw new Error(`
|
|
591
|
+
throw new Error(`Failed to parse JSON string: ${error}`);
|
|
426
592
|
}
|
|
427
593
|
} else if (typeof options === "object" && options !== null) {
|
|
428
594
|
parsedOptions = options;
|
|
429
595
|
} else {
|
|
430
|
-
throw new Error(
|
|
431
|
-
"PermitUtils :: importShared :: Invalid input type, expected ImportSharedPermitOptions, object, or string"
|
|
432
|
-
);
|
|
596
|
+
throw new Error("Invalid input type, expected ImportSharedPermitOptions, object, or string");
|
|
433
597
|
}
|
|
434
598
|
if (parsedOptions.type != null && parsedOptions.type !== "sharing") {
|
|
435
|
-
throw new Error(`
|
|
599
|
+
throw new Error(`Invalid permit type <${parsedOptions.type}>, must be "sharing"`);
|
|
436
600
|
}
|
|
437
601
|
const validation = validateImportPermitOptions({ ...parsedOptions, type: "recipient" });
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
const sealingPair = await GenerateSealingKey();
|
|
444
|
-
return {
|
|
445
|
-
...validation.data,
|
|
602
|
+
const sealingPair = GenerateSealingKey();
|
|
603
|
+
const permit = {
|
|
604
|
+
hash: PermitUtils.getHash(validation),
|
|
605
|
+
...validation,
|
|
446
606
|
sealingPair,
|
|
447
607
|
_signedDomain: void 0
|
|
448
608
|
};
|
|
609
|
+
return permit;
|
|
449
610
|
},
|
|
450
611
|
/**
|
|
451
612
|
* Sign a permit with the provided wallet client
|
|
@@ -453,11 +614,11 @@ var PermitUtils = {
|
|
|
453
614
|
sign: async (permit, publicClient, walletClient) => {
|
|
454
615
|
if (walletClient == null || walletClient.account == null) {
|
|
455
616
|
throw new Error(
|
|
456
|
-
"
|
|
617
|
+
"Missing walletClient, you must pass in a `walletClient` for the connected user to create a permit signature"
|
|
457
618
|
);
|
|
458
619
|
}
|
|
459
620
|
const primaryType = SignatureUtils.getPrimaryType(permit.type);
|
|
460
|
-
const domain = await
|
|
621
|
+
const domain = await getAclEIP712Domain(publicClient);
|
|
461
622
|
const { types, message } = SignatureUtils.getSignatureParams(PermitUtils.getPermission(permit, true), primaryType);
|
|
462
623
|
const signature = await walletClient.signTypedData({
|
|
463
624
|
domain,
|
|
@@ -486,21 +647,21 @@ var PermitUtils = {
|
|
|
486
647
|
* Create and sign a self permit in one operation
|
|
487
648
|
*/
|
|
488
649
|
createSelfAndSign: async (options, publicClient, walletClient) => {
|
|
489
|
-
const permit =
|
|
650
|
+
const permit = PermitUtils.createSelf(options);
|
|
490
651
|
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
491
652
|
},
|
|
492
653
|
/**
|
|
493
654
|
* Create and sign a sharing permit in one operation
|
|
494
655
|
*/
|
|
495
656
|
createSharingAndSign: async (options, publicClient, walletClient) => {
|
|
496
|
-
const permit =
|
|
657
|
+
const permit = PermitUtils.createSharing(options);
|
|
497
658
|
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
498
659
|
},
|
|
499
660
|
/**
|
|
500
661
|
* Import and sign a shared permit in one operation from various input formats
|
|
501
662
|
*/
|
|
502
663
|
importSharedAndSign: async (options, publicClient, walletClient) => {
|
|
503
|
-
const permit =
|
|
664
|
+
const permit = PermitUtils.importShared(options);
|
|
504
665
|
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
505
666
|
},
|
|
506
667
|
/**
|
|
@@ -517,6 +678,7 @@ var PermitUtils = {
|
|
|
517
678
|
*/
|
|
518
679
|
serialize: (permit) => {
|
|
519
680
|
return {
|
|
681
|
+
hash: permit.hash,
|
|
520
682
|
name: permit.name,
|
|
521
683
|
type: permit.type,
|
|
522
684
|
issuer: permit.issuer,
|
|
@@ -541,7 +703,7 @@ var PermitUtils = {
|
|
|
541
703
|
} else if (permit.type === "recipient") {
|
|
542
704
|
return validateImportPermit(permit);
|
|
543
705
|
} else {
|
|
544
|
-
throw new Error("
|
|
706
|
+
throw new Error("Invalid permit type");
|
|
545
707
|
}
|
|
546
708
|
},
|
|
547
709
|
/**
|
|
@@ -549,12 +711,7 @@ var PermitUtils = {
|
|
|
549
711
|
*/
|
|
550
712
|
getPermission: (permit, skipValidation = false) => {
|
|
551
713
|
if (!skipValidation) {
|
|
552
|
-
|
|
553
|
-
if (!validationResult.success) {
|
|
554
|
-
throw new Error(
|
|
555
|
-
`PermitUtils :: getPermission :: permit validation failed - ${JSON.stringify(validationResult.error, null, 2)} ${JSON.stringify(permit, null, 2)}`
|
|
556
|
-
);
|
|
557
|
-
}
|
|
714
|
+
PermitUtils.validate(permit);
|
|
558
715
|
}
|
|
559
716
|
return {
|
|
560
717
|
issuer: permit.issuer,
|
|
@@ -635,28 +792,7 @@ var PermitUtils = {
|
|
|
635
792
|
* Fetch EIP712 domain from the blockchain
|
|
636
793
|
*/
|
|
637
794
|
fetchEIP712Domain: async (publicClient) => {
|
|
638
|
-
|
|
639
|
-
const ACL_IFACE = "function acl() view returns (address)";
|
|
640
|
-
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
641
|
-
const aclAbi = parseAbi([ACL_IFACE]);
|
|
642
|
-
const aclAddress = await publicClient.readContract({
|
|
643
|
-
address: TASK_MANAGER_ADDRESS,
|
|
644
|
-
abi: aclAbi,
|
|
645
|
-
functionName: "acl"
|
|
646
|
-
});
|
|
647
|
-
const domainAbi = parseAbi([EIP712_DOMAIN_IFACE]);
|
|
648
|
-
const domain = await publicClient.readContract({
|
|
649
|
-
address: aclAddress,
|
|
650
|
-
abi: domainAbi,
|
|
651
|
-
functionName: "eip712Domain"
|
|
652
|
-
});
|
|
653
|
-
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
654
|
-
return {
|
|
655
|
-
name,
|
|
656
|
-
version,
|
|
657
|
-
chainId: Number(chainId),
|
|
658
|
-
verifyingContract
|
|
659
|
-
};
|
|
795
|
+
return getAclEIP712Domain(publicClient);
|
|
660
796
|
},
|
|
661
797
|
/**
|
|
662
798
|
* Check if permit's signed domain matches the provided domain
|
|
@@ -670,18 +806,23 @@ var PermitUtils = {
|
|
|
670
806
|
checkSignedDomainValid: async (permit, publicClient) => {
|
|
671
807
|
if (permit._signedDomain == null)
|
|
672
808
|
return false;
|
|
673
|
-
const domain = await
|
|
809
|
+
const domain = await getAclEIP712Domain(publicClient);
|
|
674
810
|
return PermitUtils.matchesDomain(permit, domain);
|
|
811
|
+
},
|
|
812
|
+
/**
|
|
813
|
+
* Check if permit passes the on-chain validation
|
|
814
|
+
*/
|
|
815
|
+
checkValidityOnChain: async (permit, publicClient) => {
|
|
816
|
+
const permission = PermitUtils.getPermission(permit);
|
|
817
|
+
return checkPermitValidityOnChain(permission, publicClient);
|
|
675
818
|
}
|
|
676
819
|
};
|
|
820
|
+
var PERMIT_STORE_DEFAULTS = {
|
|
821
|
+
permits: {},
|
|
822
|
+
activePermitHash: {}
|
|
823
|
+
};
|
|
677
824
|
var _permitStore = createStore()(
|
|
678
|
-
persist(
|
|
679
|
-
() => ({
|
|
680
|
-
permits: {},
|
|
681
|
-
activePermitHash: {}
|
|
682
|
-
}),
|
|
683
|
-
{ name: "cofhesdk-permits" }
|
|
684
|
-
)
|
|
825
|
+
persist(() => PERMIT_STORE_DEFAULTS, { name: "cofhesdk-permits" })
|
|
685
826
|
);
|
|
686
827
|
var clearStaleStore = () => {
|
|
687
828
|
const state = _permitStore.getState();
|
|
@@ -727,11 +868,11 @@ var setPermit = (chainId, account, permit) => {
|
|
|
727
868
|
state.permits[chainId] = {};
|
|
728
869
|
if (state.permits[chainId][account] == null)
|
|
729
870
|
state.permits[chainId][account] = {};
|
|
730
|
-
state.permits[chainId][account][
|
|
871
|
+
state.permits[chainId][account][permit.hash] = PermitUtils.serialize(permit);
|
|
731
872
|
})
|
|
732
873
|
);
|
|
733
874
|
};
|
|
734
|
-
var removePermit = (chainId, account, hash
|
|
875
|
+
var removePermit = (chainId, account, hash) => {
|
|
735
876
|
clearStaleStore();
|
|
736
877
|
_permitStore.setState(
|
|
737
878
|
produce((state) => {
|
|
@@ -745,15 +886,7 @@ var removePermit = (chainId, account, hash, force) => {
|
|
|
745
886
|
if (accountPermits[hash] == null)
|
|
746
887
|
return;
|
|
747
888
|
if (state.activePermitHash[chainId][account] === hash) {
|
|
748
|
-
|
|
749
|
-
if (otherPermitHash) {
|
|
750
|
-
state.activePermitHash[chainId][account] = otherPermitHash;
|
|
751
|
-
} else {
|
|
752
|
-
if (!force) {
|
|
753
|
-
throw new Error("Cannot remove the last permit without force flag");
|
|
754
|
-
}
|
|
755
|
-
state.activePermitHash[chainId][account] = void 0;
|
|
756
|
-
}
|
|
889
|
+
state.activePermitHash[chainId][account] = void 0;
|
|
757
890
|
}
|
|
758
891
|
accountPermits[hash] = void 0;
|
|
759
892
|
})
|
|
@@ -801,4 +934,4 @@ var permitStore = {
|
|
|
801
934
|
resetStore
|
|
802
935
|
};
|
|
803
936
|
|
|
804
|
-
export { GenerateSealingKey, ImportPermitOptionsValidator, ImportPermitValidator, PermitUtils, SealingKey, SelfPermitOptionsValidator, SelfPermitValidator, SharingPermitOptionsValidator, SharingPermitValidator, SignatureTypes, SignatureUtils, ValidationUtils, _permitStore, clearStaleStore, getActivePermit, getActivePermitHash, getPermit, getPermits, getSignatureTypesAndMessage, permitStore, removeActivePermitHash, removePermit, resetStore, setActivePermitHash, setPermit, validateImportPermit, validateImportPermitOptions, validateSelfPermit, validateSelfPermitOptions, validateSharingPermit, validateSharingPermitOptions };
|
|
937
|
+
export { GenerateSealingKey, ImportPermitOptionsValidator, ImportPermitValidator, MOCKS_QUERY_DECRYPTER_ADDRESS, MOCKS_ZK_VERIFIER_ADDRESS, MOCKS_ZK_VERIFIER_SIGNER_ADDRESS, MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY, PERMIT_STORE_DEFAULTS, PermitUtils, SealingKey, SelfPermitOptionsValidator, SelfPermitValidator, SharingPermitOptionsValidator, SharingPermitValidator, SignatureTypes, SignatureUtils, TASK_MANAGER_ADDRESS, TEST_BED_ADDRESS, ValidationUtils, _permitStore, addressNotZeroSchema, addressSchema, bytesNotEmptySchema, bytesSchema, clearStaleStore, getActivePermit, getActivePermitHash, getPermit, getPermits, getSignatureTypesAndMessage, permitStore, removeActivePermitHash, removePermit, resetStore, setActivePermitHash, setPermit, validateImportPermit, validateImportPermitOptions, validateSelfPermit, validateSelfPermitOptions, validateSharingPermit, validateSharingPermitOptions };
|