@cofhe/sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/adapters/ethers5.test.ts +174 -0
- package/adapters/ethers5.ts +36 -0
- package/adapters/ethers6.test.ts +169 -0
- package/adapters/ethers6.ts +36 -0
- package/adapters/hardhat-node.ts +167 -0
- package/adapters/hardhat.hh2.test.ts +159 -0
- package/adapters/hardhat.ts +36 -0
- package/adapters/index.test.ts +20 -0
- package/adapters/index.ts +5 -0
- package/adapters/smartWallet.ts +99 -0
- package/adapters/test-utils.ts +53 -0
- package/adapters/types.ts +6 -0
- package/adapters/wagmi.test.ts +156 -0
- package/adapters/wagmi.ts +17 -0
- package/chains/chains/arbSepolia.ts +14 -0
- package/chains/chains/baseSepolia.ts +14 -0
- package/chains/chains/hardhat.ts +15 -0
- package/chains/chains/localcofhe.ts +14 -0
- package/chains/chains/sepolia.ts +14 -0
- package/chains/chains.test.ts +50 -0
- package/chains/defineChain.ts +18 -0
- package/chains/index.ts +35 -0
- package/chains/types.ts +32 -0
- package/core/baseBuilder.ts +119 -0
- package/core/client.test.ts +315 -0
- package/core/client.ts +292 -0
- package/core/clientTypes.ts +108 -0
- package/core/config.test.ts +235 -0
- package/core/config.ts +220 -0
- package/core/decrypt/MockQueryDecrypterAbi.ts +129 -0
- package/core/decrypt/cofheMocksSealOutput.ts +57 -0
- package/core/decrypt/decryptHandleBuilder.ts +287 -0
- package/core/decrypt/decryptUtils.ts +28 -0
- package/core/decrypt/tnSealOutputV1.ts +59 -0
- package/core/decrypt/tnSealOutputV2.ts +298 -0
- package/core/encrypt/MockZkVerifierAbi.ts +106 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +284 -0
- package/core/encrypt/encryptInputsBuilder.test.ts +751 -0
- package/core/encrypt/encryptInputsBuilder.ts +560 -0
- package/core/encrypt/encryptUtils.ts +67 -0
- package/core/encrypt/zkPackProveVerify.ts +335 -0
- package/core/error.ts +168 -0
- package/core/fetchKeys.test.ts +195 -0
- package/core/fetchKeys.ts +144 -0
- package/core/index.ts +89 -0
- package/core/keyStore.test.ts +226 -0
- package/core/keyStore.ts +154 -0
- package/core/permits.test.ts +494 -0
- package/core/permits.ts +200 -0
- package/core/types.ts +398 -0
- package/core/utils.ts +130 -0
- package/dist/adapters.cjs +88 -0
- package/dist/adapters.d.cts +14576 -0
- package/dist/adapters.d.ts +14576 -0
- package/dist/adapters.js +83 -0
- package/dist/chains.cjs +114 -0
- package/dist/chains.d.cts +121 -0
- package/dist/chains.d.ts +121 -0
- package/dist/chains.js +1 -0
- package/dist/chunk-UGBVZNRT.js +818 -0
- package/dist/chunk-WEAZ25JO.js +105 -0
- package/dist/chunk-WGCRJCBR.js +2523 -0
- package/dist/clientTypes-5_1nwtUe.d.cts +914 -0
- package/dist/clientTypes-Es7fyi65.d.ts +914 -0
- package/dist/core.cjs +3414 -0
- package/dist/core.d.cts +111 -0
- package/dist/core.d.ts +111 -0
- package/dist/core.js +3 -0
- package/dist/node.cjs +3286 -0
- package/dist/node.d.cts +22 -0
- package/dist/node.d.ts +22 -0
- package/dist/node.js +91 -0
- package/dist/permit-fUSe6KKq.d.cts +349 -0
- package/dist/permit-fUSe6KKq.d.ts +349 -0
- package/dist/permits.cjs +871 -0
- package/dist/permits.d.cts +1045 -0
- package/dist/permits.d.ts +1045 -0
- package/dist/permits.js +1 -0
- package/dist/types-KImPrEIe.d.cts +48 -0
- package/dist/types-KImPrEIe.d.ts +48 -0
- package/dist/web.cjs +3478 -0
- package/dist/web.d.cts +38 -0
- package/dist/web.d.ts +38 -0
- package/dist/web.js +240 -0
- 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 +147 -0
- package/node/config.test.ts +68 -0
- package/node/encryptInputs.test.ts +155 -0
- package/node/index.ts +97 -0
- package/node/storage.ts +51 -0
- package/package.json +27 -15
- package/permits/index.ts +68 -0
- package/permits/localstorage.test.ts +117 -0
- package/permits/permit.test.ts +477 -0
- package/permits/permit.ts +405 -0
- package/permits/sealing.test.ts +84 -0
- package/permits/sealing.ts +131 -0
- package/permits/signature.ts +79 -0
- package/permits/store.test.ts +128 -0
- package/permits/store.ts +166 -0
- package/permits/test-utils.ts +20 -0
- package/permits/types.ts +191 -0
- package/permits/utils.ts +62 -0
- package/permits/validation.test.ts +288 -0
- package/permits/validation.ts +369 -0
- package/web/client.web.test.ts +147 -0
- package/web/config.web.test.ts +69 -0
- package/web/encryptInputs.web.test.ts +172 -0
- package/web/index.ts +161 -0
- package/web/storage.ts +34 -0
- 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
|
@@ -0,0 +1,818 @@
|
|
|
1
|
+
import { isAddress, zeroAddress, keccak256, toHex, parseAbi } from 'viem';
|
|
2
|
+
import * as nacl from 'tweetnacl';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { createStore } from 'zustand/vanilla';
|
|
5
|
+
import { persist } from 'zustand/middleware';
|
|
6
|
+
import { produce } from 'immer';
|
|
7
|
+
|
|
8
|
+
// permits/permit.ts
|
|
9
|
+
|
|
10
|
+
// permits/utils.ts
|
|
11
|
+
var fromHexString = (hexString) => {
|
|
12
|
+
const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
|
|
13
|
+
const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
|
|
14
|
+
if (!arr)
|
|
15
|
+
return new Uint8Array();
|
|
16
|
+
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
17
|
+
};
|
|
18
|
+
var toHexString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
|
|
19
|
+
function toBigInt(value) {
|
|
20
|
+
if (typeof value === "string") {
|
|
21
|
+
return BigInt(value);
|
|
22
|
+
} else if (typeof value === "number") {
|
|
23
|
+
return BigInt(value);
|
|
24
|
+
} else if (typeof value === "object") {
|
|
25
|
+
return BigInt("0x" + toHexString(value));
|
|
26
|
+
} else {
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function toBeArray(value) {
|
|
31
|
+
const bigIntValue = typeof value === "number" ? BigInt(value) : value;
|
|
32
|
+
const hex = bigIntValue.toString(16);
|
|
33
|
+
const paddedHex = hex.length % 2 === 0 ? hex : "0" + hex;
|
|
34
|
+
return fromHexString(paddedHex);
|
|
35
|
+
}
|
|
36
|
+
function isString(value) {
|
|
37
|
+
if (typeof value !== "string") {
|
|
38
|
+
throw new Error(`Expected value which is \`string\`, received value of type \`${typeof value}\`.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function isNumber(value) {
|
|
42
|
+
const is = typeof value === "number" && !Number.isNaN(value);
|
|
43
|
+
if (!is) {
|
|
44
|
+
throw new Error(`Expected value which is \`number\`, received value of type \`${typeof value}\`.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function isBigIntOrNumber(value) {
|
|
48
|
+
const is = typeof value === "bigint";
|
|
49
|
+
if (!is) {
|
|
50
|
+
try {
|
|
51
|
+
isNumber(value);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
throw new Error(`Value ${value} is not a number or bigint: ${typeof value}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function is0xPrefixed(value) {
|
|
58
|
+
return value.startsWith("0x");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// permits/sealing.ts
|
|
62
|
+
var PRIVATE_KEY_LENGTH = 64;
|
|
63
|
+
var PUBLIC_KEY_LENGTH = 64;
|
|
64
|
+
var SealingKey = class _SealingKey {
|
|
65
|
+
/**
|
|
66
|
+
* The private key used for decryption.
|
|
67
|
+
*/
|
|
68
|
+
privateKey;
|
|
69
|
+
/**
|
|
70
|
+
* The public key used for encryption.
|
|
71
|
+
*/
|
|
72
|
+
publicKey;
|
|
73
|
+
/**
|
|
74
|
+
* Constructs a SealingKey instance with the given private and public keys.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} privateKey - The private key used for decryption.
|
|
77
|
+
* @param {string} publicKey - The public key used for encryption.
|
|
78
|
+
* @throws Will throw an error if the provided keys lengths do not match
|
|
79
|
+
* the required lengths for private and public keys.
|
|
80
|
+
*/
|
|
81
|
+
constructor(privateKey, publicKey) {
|
|
82
|
+
if (privateKey.length !== PRIVATE_KEY_LENGTH) {
|
|
83
|
+
throw new Error(`Private key must be of length ${PRIVATE_KEY_LENGTH}`);
|
|
84
|
+
}
|
|
85
|
+
if (publicKey.length !== PUBLIC_KEY_LENGTH) {
|
|
86
|
+
throw new Error(`Public key must be of length ${PUBLIC_KEY_LENGTH}`);
|
|
87
|
+
}
|
|
88
|
+
this.privateKey = privateKey;
|
|
89
|
+
this.publicKey = publicKey;
|
|
90
|
+
}
|
|
91
|
+
unseal = (parsedData) => {
|
|
92
|
+
const nonce = parsedData.nonce instanceof Uint8Array ? parsedData.nonce : new Uint8Array(parsedData.nonce);
|
|
93
|
+
const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
|
|
94
|
+
const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
|
|
95
|
+
const privateKeyBytes = fromHexString(this.privateKey);
|
|
96
|
+
const decryptedMessage = nacl.box.open(dataToDecrypt, nonce, ephemPublicKey, privateKeyBytes);
|
|
97
|
+
if (!decryptedMessage) {
|
|
98
|
+
throw new Error("Failed to decrypt message");
|
|
99
|
+
}
|
|
100
|
+
return toBigInt(decryptedMessage);
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Serializes the SealingKey to a JSON object.
|
|
104
|
+
*/
|
|
105
|
+
serialize = () => {
|
|
106
|
+
return {
|
|
107
|
+
privateKey: this.privateKey,
|
|
108
|
+
publicKey: this.publicKey
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Deserializes the SealingKey from a JSON object.
|
|
113
|
+
*/
|
|
114
|
+
static deserialize = (privateKey, publicKey) => {
|
|
115
|
+
return new _SealingKey(privateKey, publicKey);
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Seals (encrypts) the provided message for a receiver with the specified public key.
|
|
119
|
+
*
|
|
120
|
+
* @param {bigint | number} value - The message to be encrypted.
|
|
121
|
+
* @param {string} publicKey - The public key of the intended recipient.
|
|
122
|
+
* @returns string - The encrypted message in hexadecimal format.
|
|
123
|
+
* @static
|
|
124
|
+
* @throws Will throw if the provided publicKey or value do not meet defined preconditions.
|
|
125
|
+
*/
|
|
126
|
+
static seal = (value, publicKey) => {
|
|
127
|
+
isString(publicKey);
|
|
128
|
+
isBigIntOrNumber(value);
|
|
129
|
+
const ephemeralKeyPair = nacl.box.keyPair();
|
|
130
|
+
const nonce = nacl.randomBytes(nacl.box.nonceLength);
|
|
131
|
+
const encryptedMessage = nacl.box(toBeArray(value), nonce, fromHexString(publicKey), ephemeralKeyPair.secretKey);
|
|
132
|
+
return {
|
|
133
|
+
data: encryptedMessage,
|
|
134
|
+
public_key: ephemeralKeyPair.publicKey,
|
|
135
|
+
nonce
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
var GenerateSealingKey = () => {
|
|
140
|
+
const sodiumKeypair = nacl.box.keyPair();
|
|
141
|
+
return new SealingKey(toHexString(sodiumKeypair.secretKey), toHexString(sodiumKeypair.publicKey));
|
|
142
|
+
};
|
|
143
|
+
var SerializedSealingPair = z.object({
|
|
144
|
+
privateKey: z.string(),
|
|
145
|
+
publicKey: z.string()
|
|
146
|
+
});
|
|
147
|
+
var DEFAULT_EXPIRATION_FN = () => Math.round(Date.now() / 1e3) + 7 * 24 * 60 * 60;
|
|
148
|
+
var zPermitWithDefaults = z.object({
|
|
149
|
+
name: z.string().optional().default("Unnamed Permit"),
|
|
150
|
+
type: z.enum(["self", "sharing", "recipient"]),
|
|
151
|
+
issuer: z.string().refine((val) => isAddress(val), {
|
|
152
|
+
message: "Permit issuer :: invalid address"
|
|
153
|
+
}).refine((val) => val !== zeroAddress, {
|
|
154
|
+
message: "Permit issuer :: must not be zeroAddress"
|
|
155
|
+
}),
|
|
156
|
+
expiration: z.number().optional().default(DEFAULT_EXPIRATION_FN),
|
|
157
|
+
recipient: z.string().optional().default(zeroAddress).refine((val) => isAddress(val), {
|
|
158
|
+
message: "Permit recipient :: invalid address"
|
|
159
|
+
}),
|
|
160
|
+
validatorId: z.number().optional().default(0),
|
|
161
|
+
validatorContract: z.string().optional().default(zeroAddress).refine((val) => isAddress(val), {
|
|
162
|
+
message: "Permit validatorContract :: invalid address"
|
|
163
|
+
}),
|
|
164
|
+
issuerSignature: z.string().optional().default("0x"),
|
|
165
|
+
recipientSignature: z.string().optional().default("0x")
|
|
166
|
+
});
|
|
167
|
+
var zPermitWithSealingPair = zPermitWithDefaults.extend({
|
|
168
|
+
sealingPair: SerializedSealingPair.optional()
|
|
169
|
+
});
|
|
170
|
+
var ValidatorContractRefinement = [
|
|
171
|
+
(data) => data.validatorId !== 0 && data.validatorContract !== zeroAddress || data.validatorId === 0 && data.validatorContract === zeroAddress,
|
|
172
|
+
{
|
|
173
|
+
message: "Permit external validator :: validatorId and validatorContract must either both be set or both be unset.",
|
|
174
|
+
path: ["validatorId", "validatorContract"]
|
|
175
|
+
}
|
|
176
|
+
];
|
|
177
|
+
var SelfPermitOptionsValidator = z.object({
|
|
178
|
+
type: z.literal("self").optional().default("self"),
|
|
179
|
+
issuer: z.string().refine((val) => isAddress(val), {
|
|
180
|
+
message: "Self permit issuer :: invalid address"
|
|
181
|
+
}).refine((val) => is0xPrefixed(val), {
|
|
182
|
+
message: "Self permit issuer :: must be 0x prefixed"
|
|
183
|
+
}).refine((val) => val !== zeroAddress, {
|
|
184
|
+
message: "Self permit issuer :: must not be zeroAddress"
|
|
185
|
+
}),
|
|
186
|
+
name: z.string().optional().default("Unnamed Permit"),
|
|
187
|
+
expiration: z.number().optional().default(DEFAULT_EXPIRATION_FN),
|
|
188
|
+
recipient: z.string().optional().default(zeroAddress).refine((val) => isAddress(val), {
|
|
189
|
+
message: "Self permit recipient :: invalid address"
|
|
190
|
+
}).refine((val) => is0xPrefixed(val), {
|
|
191
|
+
message: "Self permit recipient :: must be 0x prefixed"
|
|
192
|
+
}).refine((val) => val === zeroAddress, {
|
|
193
|
+
message: "Self permit recipient :: must be zeroAddress"
|
|
194
|
+
}),
|
|
195
|
+
validatorId: z.number().optional().default(0),
|
|
196
|
+
validatorContract: z.string().optional().default(zeroAddress).refine((val) => isAddress(val), {
|
|
197
|
+
message: "Self permit validatorContract :: invalid address"
|
|
198
|
+
}),
|
|
199
|
+
issuerSignature: z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
200
|
+
message: "Self permit issuerSignature :: must be 0x prefixed"
|
|
201
|
+
}),
|
|
202
|
+
recipientSignature: z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
203
|
+
message: "Self permit recipientSignature :: must be 0x prefixed"
|
|
204
|
+
})
|
|
205
|
+
}).refine(...ValidatorContractRefinement);
|
|
206
|
+
var SelfPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "self", {
|
|
207
|
+
message: "Self permit :: type must be 'self'"
|
|
208
|
+
}).refine((data) => data.recipient === zeroAddress, {
|
|
209
|
+
message: "Self permit :: recipient must be zeroAddress"
|
|
210
|
+
}).refine((data) => data.issuerSignature !== "0x", {
|
|
211
|
+
message: "Self permit :: issuerSignature must be populated"
|
|
212
|
+
}).refine((data) => data.recipientSignature === "0x", {
|
|
213
|
+
message: "Self permit :: recipientSignature must be empty"
|
|
214
|
+
}).refine(...ValidatorContractRefinement);
|
|
215
|
+
var SharingPermitOptionsValidator = z.object({
|
|
216
|
+
type: z.literal("sharing").optional().default("sharing"),
|
|
217
|
+
issuer: z.string().refine((val) => isAddress(val), {
|
|
218
|
+
message: "Sharing permit issuer :: invalid address"
|
|
219
|
+
}).refine((val) => is0xPrefixed(val), {
|
|
220
|
+
message: "Sharing permit issuer :: must be 0x prefixed"
|
|
221
|
+
}).refine((val) => val !== zeroAddress, {
|
|
222
|
+
message: "Sharing permit issuer :: must not be zeroAddress"
|
|
223
|
+
}),
|
|
224
|
+
recipient: z.string().refine((val) => isAddress(val), {
|
|
225
|
+
message: "Sharing permit recipient :: invalid address"
|
|
226
|
+
}).refine((val) => is0xPrefixed(val), {
|
|
227
|
+
message: "Sharing permit recipient :: must be 0x prefixed"
|
|
228
|
+
}).refine((val) => val !== zeroAddress, {
|
|
229
|
+
message: "Sharing permit recipient :: must not be zeroAddress"
|
|
230
|
+
}),
|
|
231
|
+
name: z.string().optional().default("Unnamed Permit"),
|
|
232
|
+
expiration: z.number().optional().default(DEFAULT_EXPIRATION_FN),
|
|
233
|
+
validatorId: z.number().optional().default(0),
|
|
234
|
+
validatorContract: z.string().optional().default(zeroAddress).refine((val) => isAddress(val), {
|
|
235
|
+
message: "Sharing permit validatorContract :: invalid address"
|
|
236
|
+
}),
|
|
237
|
+
issuerSignature: z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
238
|
+
message: "Sharing permit issuerSignature :: must be 0x prefixed"
|
|
239
|
+
}),
|
|
240
|
+
recipientSignature: z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
241
|
+
message: "Sharing permit recipientSignature :: must be 0x prefixed"
|
|
242
|
+
})
|
|
243
|
+
}).refine(...ValidatorContractRefinement);
|
|
244
|
+
var SharingPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "sharing", {
|
|
245
|
+
message: "Sharing permit :: type must be 'sharing'"
|
|
246
|
+
}).refine((data) => data.recipient !== zeroAddress, {
|
|
247
|
+
message: "Sharing permit :: recipient must not be zeroAddress"
|
|
248
|
+
}).refine((data) => data.issuerSignature !== "0x", {
|
|
249
|
+
message: "Sharing permit :: issuerSignature must be populated"
|
|
250
|
+
}).refine((data) => data.recipientSignature === "0x", {
|
|
251
|
+
message: "Sharing permit :: recipientSignature must be empty"
|
|
252
|
+
}).refine(...ValidatorContractRefinement);
|
|
253
|
+
var ImportPermitOptionsValidator = z.object({
|
|
254
|
+
type: z.literal("recipient").optional().default("recipient"),
|
|
255
|
+
issuer: z.string().refine((val) => isAddress(val), {
|
|
256
|
+
message: "Import permit issuer :: invalid address"
|
|
257
|
+
}).refine((val) => is0xPrefixed(val), {
|
|
258
|
+
message: "Import permit issuer :: must be 0x prefixed"
|
|
259
|
+
}).refine((val) => val !== zeroAddress, {
|
|
260
|
+
message: "Import permit issuer :: must not be zeroAddress"
|
|
261
|
+
}),
|
|
262
|
+
recipient: z.string().refine((val) => isAddress(val), {
|
|
263
|
+
message: "Import permit recipient :: invalid address"
|
|
264
|
+
}).refine((val) => is0xPrefixed(val), {
|
|
265
|
+
message: "Import permit recipient :: must be 0x prefixed"
|
|
266
|
+
}).refine((val) => val !== zeroAddress, {
|
|
267
|
+
message: "Import permit recipient :: must not be zeroAddress"
|
|
268
|
+
}),
|
|
269
|
+
issuerSignature: z.string().refine((val) => is0xPrefixed(val), {
|
|
270
|
+
message: "Import permit issuerSignature :: must be 0x prefixed"
|
|
271
|
+
}).refine((val) => val !== "0x", {
|
|
272
|
+
message: "Import permit :: issuerSignature must be provided"
|
|
273
|
+
}),
|
|
274
|
+
name: z.string().optional().default("Unnamed Permit"),
|
|
275
|
+
expiration: z.number().optional().default(DEFAULT_EXPIRATION_FN),
|
|
276
|
+
validatorId: z.number().optional().default(0),
|
|
277
|
+
validatorContract: z.string().optional().default(zeroAddress).refine((val) => isAddress(val), {
|
|
278
|
+
message: "Import permit validatorContract :: invalid address"
|
|
279
|
+
}),
|
|
280
|
+
recipientSignature: z.string().optional().default("0x").refine((val) => is0xPrefixed(val), {
|
|
281
|
+
message: "Import permit recipientSignature :: must be 0x prefixed"
|
|
282
|
+
})
|
|
283
|
+
}).refine(...ValidatorContractRefinement);
|
|
284
|
+
var ImportPermitValidator = zPermitWithSealingPair.refine((data) => data.type === "recipient", {
|
|
285
|
+
message: "Import permit :: type must be 'recipient'"
|
|
286
|
+
}).refine((data) => data.recipient !== zeroAddress, {
|
|
287
|
+
message: "Import permit :: recipient must not be zeroAddress"
|
|
288
|
+
}).refine((data) => data.issuerSignature !== "0x", {
|
|
289
|
+
message: "Import permit :: issuerSignature must be populated"
|
|
290
|
+
}).refine((data) => data.recipientSignature !== "0x", {
|
|
291
|
+
message: "Import permit :: recipientSignature must be populated"
|
|
292
|
+
}).refine(...ValidatorContractRefinement);
|
|
293
|
+
var validateSelfPermitOptions = (options) => SelfPermitOptionsValidator.safeParse(options);
|
|
294
|
+
var validateSharingPermitOptions = (options) => SharingPermitOptionsValidator.safeParse(options);
|
|
295
|
+
var validateImportPermitOptions = (options) => ImportPermitOptionsValidator.safeParse(options);
|
|
296
|
+
var validateSelfPermit = (permit) => SelfPermitValidator.safeParse(permit);
|
|
297
|
+
var validateSharingPermit = (permit) => SharingPermitValidator.safeParse(permit);
|
|
298
|
+
var validateImportPermit = (permit) => ImportPermitValidator.safeParse(permit);
|
|
299
|
+
var ValidationUtils = {
|
|
300
|
+
/**
|
|
301
|
+
* Check if permit is expired
|
|
302
|
+
*/
|
|
303
|
+
isExpired: (permit) => {
|
|
304
|
+
return permit.expiration < Math.floor(Date.now() / 1e3);
|
|
305
|
+
},
|
|
306
|
+
/**
|
|
307
|
+
* Check if permit is signed by the active party
|
|
308
|
+
*/
|
|
309
|
+
isSigned: (permit) => {
|
|
310
|
+
if (permit.type === "self" || permit.type === "sharing") {
|
|
311
|
+
return permit.issuerSignature !== "0x";
|
|
312
|
+
}
|
|
313
|
+
if (permit.type === "recipient") {
|
|
314
|
+
return permit.recipientSignature !== "0x";
|
|
315
|
+
}
|
|
316
|
+
return false;
|
|
317
|
+
},
|
|
318
|
+
/**
|
|
319
|
+
* Overall validity checker of a permit
|
|
320
|
+
*/
|
|
321
|
+
isValid: (permit) => {
|
|
322
|
+
if (ValidationUtils.isExpired(permit)) {
|
|
323
|
+
return { valid: false, error: "expired" };
|
|
324
|
+
}
|
|
325
|
+
if (!ValidationUtils.isSigned(permit)) {
|
|
326
|
+
return { valid: false, error: "not-signed" };
|
|
327
|
+
}
|
|
328
|
+
return { valid: true, error: null };
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// permits/signature.ts
|
|
333
|
+
var PermitSignatureAllFields = [
|
|
334
|
+
{ name: "issuer", type: "address" },
|
|
335
|
+
{ name: "expiration", type: "uint64" },
|
|
336
|
+
{ name: "recipient", type: "address" },
|
|
337
|
+
{ name: "validatorId", type: "uint256" },
|
|
338
|
+
{ name: "validatorContract", type: "address" },
|
|
339
|
+
{ name: "sealingKey", type: "bytes32" },
|
|
340
|
+
{ name: "issuerSignature", type: "bytes" }
|
|
341
|
+
];
|
|
342
|
+
var SignatureTypes = {
|
|
343
|
+
PermissionedV2IssuerSelf: [
|
|
344
|
+
"issuer",
|
|
345
|
+
"expiration",
|
|
346
|
+
"recipient",
|
|
347
|
+
"validatorId",
|
|
348
|
+
"validatorContract",
|
|
349
|
+
"sealingKey"
|
|
350
|
+
],
|
|
351
|
+
PermissionedV2IssuerShared: [
|
|
352
|
+
"issuer",
|
|
353
|
+
"expiration",
|
|
354
|
+
"recipient",
|
|
355
|
+
"validatorId",
|
|
356
|
+
"validatorContract"
|
|
357
|
+
],
|
|
358
|
+
PermissionedV2Recipient: ["sealingKey", "issuerSignature"]
|
|
359
|
+
};
|
|
360
|
+
var getSignatureTypesAndMessage = (primaryType, fields, values) => {
|
|
361
|
+
const types = {
|
|
362
|
+
[primaryType]: PermitSignatureAllFields.filter((fieldType) => fields.includes(fieldType.name))
|
|
363
|
+
};
|
|
364
|
+
const message = {};
|
|
365
|
+
fields.forEach((field) => {
|
|
366
|
+
if (field in values) {
|
|
367
|
+
message[field] = values[field];
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
return { types, primaryType, message };
|
|
371
|
+
};
|
|
372
|
+
var SignatureUtils = {
|
|
373
|
+
/**
|
|
374
|
+
* Get signature parameters for a permit
|
|
375
|
+
*/
|
|
376
|
+
getSignatureParams: (permit, primaryType) => {
|
|
377
|
+
return getSignatureTypesAndMessage(primaryType, SignatureTypes[primaryType], permit);
|
|
378
|
+
},
|
|
379
|
+
/**
|
|
380
|
+
* Determine the required signature type based on permit type
|
|
381
|
+
*/
|
|
382
|
+
getPrimaryType: (permitType) => {
|
|
383
|
+
if (permitType === "self")
|
|
384
|
+
return "PermissionedV2IssuerSelf";
|
|
385
|
+
if (permitType === "sharing")
|
|
386
|
+
return "PermissionedV2IssuerShared";
|
|
387
|
+
if (permitType === "recipient")
|
|
388
|
+
return "PermissionedV2Recipient";
|
|
389
|
+
throw new Error(`Unknown permit type: ${permitType}`);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
// permits/permit.ts
|
|
394
|
+
var PermitUtils = {
|
|
395
|
+
/**
|
|
396
|
+
* Create a self permit for personal use
|
|
397
|
+
*/
|
|
398
|
+
createSelf: (options) => {
|
|
399
|
+
const validation = validateSelfPermitOptions(options);
|
|
400
|
+
if (!validation.success) {
|
|
401
|
+
throw new Error(
|
|
402
|
+
"PermitUtils :: createSelf :: Parsing SelfPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
const sealingPair = GenerateSealingKey();
|
|
406
|
+
const permit = {
|
|
407
|
+
...validation.data,
|
|
408
|
+
sealingPair,
|
|
409
|
+
_signedDomain: void 0
|
|
410
|
+
};
|
|
411
|
+
return permit;
|
|
412
|
+
},
|
|
413
|
+
/**
|
|
414
|
+
* Create a sharing permit to be shared with another user
|
|
415
|
+
*/
|
|
416
|
+
createSharing: (options) => {
|
|
417
|
+
const validation = validateSharingPermitOptions(options);
|
|
418
|
+
if (!validation.success) {
|
|
419
|
+
throw new Error(
|
|
420
|
+
"PermitUtils :: createSharing :: Parsing SharingPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
const sealingPair = GenerateSealingKey();
|
|
424
|
+
const permit = {
|
|
425
|
+
...validation.data,
|
|
426
|
+
sealingPair,
|
|
427
|
+
_signedDomain: void 0
|
|
428
|
+
};
|
|
429
|
+
return permit;
|
|
430
|
+
},
|
|
431
|
+
/**
|
|
432
|
+
* Import a shared permit from various input formats
|
|
433
|
+
*/
|
|
434
|
+
importShared: (options) => {
|
|
435
|
+
let parsedOptions;
|
|
436
|
+
if (typeof options === "string") {
|
|
437
|
+
try {
|
|
438
|
+
parsedOptions = JSON.parse(options);
|
|
439
|
+
} catch (error) {
|
|
440
|
+
throw new Error(`PermitUtils :: importShared :: Failed to parse JSON string: ${error}`);
|
|
441
|
+
}
|
|
442
|
+
} else if (typeof options === "object" && options !== null) {
|
|
443
|
+
parsedOptions = options;
|
|
444
|
+
} else {
|
|
445
|
+
throw new Error(
|
|
446
|
+
"PermitUtils :: importShared :: Invalid input type, expected ImportSharedPermitOptions, object, or string"
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
if (parsedOptions.type != null && parsedOptions.type !== "sharing") {
|
|
450
|
+
throw new Error(`PermitUtils :: importShared :: Invalid permit type <${parsedOptions.type}>, must be "sharing"`);
|
|
451
|
+
}
|
|
452
|
+
const validation = validateImportPermitOptions({ ...parsedOptions, type: "recipient" });
|
|
453
|
+
if (!validation.success) {
|
|
454
|
+
throw new Error(
|
|
455
|
+
"PermitUtils :: importShared :: Parsing ImportPermitOptions failed " + JSON.stringify(validation.error, null, 2)
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
const sealingPair = GenerateSealingKey();
|
|
459
|
+
const permit = {
|
|
460
|
+
...validation.data,
|
|
461
|
+
sealingPair,
|
|
462
|
+
_signedDomain: void 0
|
|
463
|
+
};
|
|
464
|
+
return permit;
|
|
465
|
+
},
|
|
466
|
+
/**
|
|
467
|
+
* Sign a permit with the provided wallet client
|
|
468
|
+
*/
|
|
469
|
+
sign: async (permit, publicClient, walletClient) => {
|
|
470
|
+
if (walletClient == null || walletClient.account == null) {
|
|
471
|
+
throw new Error(
|
|
472
|
+
"PermitUtils :: sign - walletClient undefined, you must pass in a `walletClient` for the connected user to create a permit signature"
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
const primaryType = SignatureUtils.getPrimaryType(permit.type);
|
|
476
|
+
const domain = await PermitUtils.fetchEIP712Domain(publicClient);
|
|
477
|
+
const { types, message } = SignatureUtils.getSignatureParams(PermitUtils.getPermission(permit, true), primaryType);
|
|
478
|
+
const signature = await walletClient.signTypedData({
|
|
479
|
+
domain,
|
|
480
|
+
types,
|
|
481
|
+
primaryType,
|
|
482
|
+
message,
|
|
483
|
+
account: walletClient.account
|
|
484
|
+
});
|
|
485
|
+
let updatedPermit;
|
|
486
|
+
if (permit.type === "self" || permit.type === "sharing") {
|
|
487
|
+
updatedPermit = {
|
|
488
|
+
...permit,
|
|
489
|
+
issuerSignature: signature,
|
|
490
|
+
_signedDomain: domain
|
|
491
|
+
};
|
|
492
|
+
} else {
|
|
493
|
+
updatedPermit = {
|
|
494
|
+
...permit,
|
|
495
|
+
recipientSignature: signature,
|
|
496
|
+
_signedDomain: domain
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
return updatedPermit;
|
|
500
|
+
},
|
|
501
|
+
/**
|
|
502
|
+
* Create and sign a self permit in one operation
|
|
503
|
+
*/
|
|
504
|
+
createSelfAndSign: async (options, publicClient, walletClient) => {
|
|
505
|
+
const permit = PermitUtils.createSelf(options);
|
|
506
|
+
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
507
|
+
},
|
|
508
|
+
/**
|
|
509
|
+
* Create and sign a sharing permit in one operation
|
|
510
|
+
*/
|
|
511
|
+
createSharingAndSign: async (options, publicClient, walletClient) => {
|
|
512
|
+
const permit = PermitUtils.createSharing(options);
|
|
513
|
+
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
514
|
+
},
|
|
515
|
+
/**
|
|
516
|
+
* Import and sign a shared permit in one operation from various input formats
|
|
517
|
+
*/
|
|
518
|
+
importSharedAndSign: async (options, publicClient, walletClient) => {
|
|
519
|
+
const permit = PermitUtils.importShared(options);
|
|
520
|
+
return PermitUtils.sign(permit, publicClient, walletClient);
|
|
521
|
+
},
|
|
522
|
+
/**
|
|
523
|
+
* Deserialize a permit from serialized data
|
|
524
|
+
*/
|
|
525
|
+
deserialize: (data) => {
|
|
526
|
+
return {
|
|
527
|
+
...data,
|
|
528
|
+
sealingPair: SealingKey.deserialize(data.sealingPair.privateKey, data.sealingPair.publicKey)
|
|
529
|
+
};
|
|
530
|
+
},
|
|
531
|
+
/**
|
|
532
|
+
* Serialize a permit for storage
|
|
533
|
+
*/
|
|
534
|
+
serialize: (permit) => {
|
|
535
|
+
return {
|
|
536
|
+
name: permit.name,
|
|
537
|
+
type: permit.type,
|
|
538
|
+
issuer: permit.issuer,
|
|
539
|
+
expiration: permit.expiration,
|
|
540
|
+
recipient: permit.recipient,
|
|
541
|
+
validatorId: permit.validatorId,
|
|
542
|
+
validatorContract: permit.validatorContract,
|
|
543
|
+
issuerSignature: permit.issuerSignature,
|
|
544
|
+
recipientSignature: permit.recipientSignature,
|
|
545
|
+
_signedDomain: permit._signedDomain,
|
|
546
|
+
sealingPair: permit.sealingPair.serialize()
|
|
547
|
+
};
|
|
548
|
+
},
|
|
549
|
+
/**
|
|
550
|
+
* Validate a permit
|
|
551
|
+
*/
|
|
552
|
+
validate: (permit) => {
|
|
553
|
+
if (permit.type === "self") {
|
|
554
|
+
return validateSelfPermit(permit);
|
|
555
|
+
} else if (permit.type === "sharing") {
|
|
556
|
+
return validateSharingPermit(permit);
|
|
557
|
+
} else if (permit.type === "recipient") {
|
|
558
|
+
return validateImportPermit(permit);
|
|
559
|
+
} else {
|
|
560
|
+
throw new Error("PermitUtils :: validate :: Invalid permit type");
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
/**
|
|
564
|
+
* Get the permission object from a permit (for use in contracts)
|
|
565
|
+
*/
|
|
566
|
+
getPermission: (permit, skipValidation = false) => {
|
|
567
|
+
if (!skipValidation) {
|
|
568
|
+
const validationResult = PermitUtils.validate(permit);
|
|
569
|
+
if (!validationResult.success) {
|
|
570
|
+
throw new Error(
|
|
571
|
+
`PermitUtils :: getPermission :: permit validation failed - ${JSON.stringify(validationResult.error, null, 2)} ${JSON.stringify(permit, null, 2)}`
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return {
|
|
576
|
+
issuer: permit.issuer,
|
|
577
|
+
expiration: permit.expiration,
|
|
578
|
+
recipient: permit.recipient,
|
|
579
|
+
validatorId: permit.validatorId,
|
|
580
|
+
validatorContract: permit.validatorContract,
|
|
581
|
+
sealingKey: `0x${permit.sealingPair.publicKey}`,
|
|
582
|
+
issuerSignature: permit.issuerSignature,
|
|
583
|
+
recipientSignature: permit.recipientSignature
|
|
584
|
+
};
|
|
585
|
+
},
|
|
586
|
+
/**
|
|
587
|
+
* Get a stable hash for the permit (used as key in storage)
|
|
588
|
+
*/
|
|
589
|
+
getHash: (permit) => {
|
|
590
|
+
const data = JSON.stringify({
|
|
591
|
+
type: permit.type,
|
|
592
|
+
issuer: permit.issuer,
|
|
593
|
+
expiration: permit.expiration,
|
|
594
|
+
recipient: permit.recipient,
|
|
595
|
+
validatorId: permit.validatorId,
|
|
596
|
+
validatorContract: permit.validatorContract
|
|
597
|
+
});
|
|
598
|
+
return keccak256(toHex(data));
|
|
599
|
+
},
|
|
600
|
+
/**
|
|
601
|
+
* Export permit data for sharing (removes sensitive fields)
|
|
602
|
+
*/
|
|
603
|
+
export: (permit) => {
|
|
604
|
+
const cleanedPermit = {
|
|
605
|
+
name: permit.name,
|
|
606
|
+
type: permit.type,
|
|
607
|
+
issuer: permit.issuer,
|
|
608
|
+
expiration: permit.expiration
|
|
609
|
+
};
|
|
610
|
+
if (permit.recipient !== zeroAddress)
|
|
611
|
+
cleanedPermit.recipient = permit.recipient;
|
|
612
|
+
if (permit.validatorId !== 0)
|
|
613
|
+
cleanedPermit.validatorId = permit.validatorId;
|
|
614
|
+
if (permit.validatorContract !== zeroAddress)
|
|
615
|
+
cleanedPermit.validatorContract = permit.validatorContract;
|
|
616
|
+
if (permit.type === "sharing" && permit.issuerSignature !== "0x")
|
|
617
|
+
cleanedPermit.issuerSignature = permit.issuerSignature;
|
|
618
|
+
return JSON.stringify(cleanedPermit, void 0, 2);
|
|
619
|
+
},
|
|
620
|
+
/**
|
|
621
|
+
* Unseal encrypted data using the permit's sealing key
|
|
622
|
+
*/
|
|
623
|
+
unseal: (permit, ciphertext) => {
|
|
624
|
+
return permit.sealingPair.unseal(ciphertext);
|
|
625
|
+
},
|
|
626
|
+
/**
|
|
627
|
+
* Check if permit is expired
|
|
628
|
+
*/
|
|
629
|
+
isExpired: (permit) => {
|
|
630
|
+
return ValidationUtils.isExpired(permit);
|
|
631
|
+
},
|
|
632
|
+
/**
|
|
633
|
+
* Check if permit is signed
|
|
634
|
+
*/
|
|
635
|
+
isSigned: (permit) => {
|
|
636
|
+
return ValidationUtils.isSigned(permit);
|
|
637
|
+
},
|
|
638
|
+
/**
|
|
639
|
+
* Check if permit is valid
|
|
640
|
+
*/
|
|
641
|
+
isValid: (permit) => {
|
|
642
|
+
return ValidationUtils.isValid(permit);
|
|
643
|
+
},
|
|
644
|
+
/**
|
|
645
|
+
* Update permit name (returns new permit instance)
|
|
646
|
+
*/
|
|
647
|
+
updateName: (permit, name) => {
|
|
648
|
+
return { ...permit, name };
|
|
649
|
+
},
|
|
650
|
+
/**
|
|
651
|
+
* Fetch EIP712 domain from the blockchain
|
|
652
|
+
*/
|
|
653
|
+
fetchEIP712Domain: async (publicClient) => {
|
|
654
|
+
const TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
655
|
+
const ACL_IFACE = "function acl() view returns (address)";
|
|
656
|
+
const EIP712_DOMAIN_IFACE = "function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)";
|
|
657
|
+
const aclAbi = parseAbi([ACL_IFACE]);
|
|
658
|
+
const aclAddress = await publicClient.readContract({
|
|
659
|
+
address: TASK_MANAGER_ADDRESS,
|
|
660
|
+
abi: aclAbi,
|
|
661
|
+
functionName: "acl"
|
|
662
|
+
});
|
|
663
|
+
const domainAbi = parseAbi([EIP712_DOMAIN_IFACE]);
|
|
664
|
+
const domain = await publicClient.readContract({
|
|
665
|
+
address: aclAddress,
|
|
666
|
+
abi: domainAbi,
|
|
667
|
+
functionName: "eip712Domain"
|
|
668
|
+
});
|
|
669
|
+
const [_fields, name, version, chainId, verifyingContract, _salt, _extensions] = domain;
|
|
670
|
+
return {
|
|
671
|
+
name,
|
|
672
|
+
version,
|
|
673
|
+
chainId: Number(chainId),
|
|
674
|
+
verifyingContract
|
|
675
|
+
};
|
|
676
|
+
},
|
|
677
|
+
/**
|
|
678
|
+
* Check if permit's signed domain matches the provided domain
|
|
679
|
+
*/
|
|
680
|
+
matchesDomain: (permit, domain) => {
|
|
681
|
+
return permit._signedDomain?.name === domain.name && permit._signedDomain?.version === domain.version && permit._signedDomain?.verifyingContract === domain.verifyingContract && permit._signedDomain?.chainId === domain.chainId;
|
|
682
|
+
},
|
|
683
|
+
/**
|
|
684
|
+
* Check if permit's signed domain is valid for the current chain
|
|
685
|
+
*/
|
|
686
|
+
checkSignedDomainValid: async (permit, publicClient) => {
|
|
687
|
+
if (permit._signedDomain == null)
|
|
688
|
+
return false;
|
|
689
|
+
const domain = await PermitUtils.fetchEIP712Domain(publicClient);
|
|
690
|
+
return PermitUtils.matchesDomain(permit, domain);
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
var PERMIT_STORE_DEFAULTS = {
|
|
694
|
+
permits: {},
|
|
695
|
+
activePermitHash: {}
|
|
696
|
+
};
|
|
697
|
+
var _permitStore = createStore()(
|
|
698
|
+
persist(() => PERMIT_STORE_DEFAULTS, { name: "cofhesdk-permits" })
|
|
699
|
+
);
|
|
700
|
+
var clearStaleStore = () => {
|
|
701
|
+
const state = _permitStore.getState();
|
|
702
|
+
const hasExpectedStructure = state && typeof state === "object" && "permits" in state && "activePermitHash" in state && typeof state.permits === "object" && typeof state.activePermitHash === "object";
|
|
703
|
+
if (hasExpectedStructure)
|
|
704
|
+
return;
|
|
705
|
+
_permitStore.setState({ permits: {}, activePermitHash: {} });
|
|
706
|
+
};
|
|
707
|
+
var getPermit = (chainId, account, hash) => {
|
|
708
|
+
clearStaleStore();
|
|
709
|
+
if (chainId == null || account == null || hash == null)
|
|
710
|
+
return;
|
|
711
|
+
const savedPermit = _permitStore.getState().permits[chainId]?.[account]?.[hash];
|
|
712
|
+
if (savedPermit == null)
|
|
713
|
+
return;
|
|
714
|
+
return PermitUtils.deserialize(savedPermit);
|
|
715
|
+
};
|
|
716
|
+
var getActivePermit = (chainId, account) => {
|
|
717
|
+
clearStaleStore();
|
|
718
|
+
if (chainId == null || account == null)
|
|
719
|
+
return;
|
|
720
|
+
const activePermitHash = _permitStore.getState().activePermitHash[chainId]?.[account];
|
|
721
|
+
return getPermit(chainId, account, activePermitHash);
|
|
722
|
+
};
|
|
723
|
+
var getPermits = (chainId, account) => {
|
|
724
|
+
clearStaleStore();
|
|
725
|
+
if (chainId == null || account == null)
|
|
726
|
+
return {};
|
|
727
|
+
return Object.entries(_permitStore.getState().permits[chainId]?.[account] ?? {}).reduce(
|
|
728
|
+
(acc, [hash, permit]) => {
|
|
729
|
+
if (permit == void 0)
|
|
730
|
+
return acc;
|
|
731
|
+
return { ...acc, [hash]: PermitUtils.deserialize(permit) };
|
|
732
|
+
},
|
|
733
|
+
{}
|
|
734
|
+
);
|
|
735
|
+
};
|
|
736
|
+
var setPermit = (chainId, account, permit) => {
|
|
737
|
+
clearStaleStore();
|
|
738
|
+
_permitStore.setState(
|
|
739
|
+
produce((state) => {
|
|
740
|
+
if (state.permits[chainId] == null)
|
|
741
|
+
state.permits[chainId] = {};
|
|
742
|
+
if (state.permits[chainId][account] == null)
|
|
743
|
+
state.permits[chainId][account] = {};
|
|
744
|
+
state.permits[chainId][account][PermitUtils.getHash(permit)] = PermitUtils.serialize(permit);
|
|
745
|
+
})
|
|
746
|
+
);
|
|
747
|
+
};
|
|
748
|
+
var removePermit = (chainId, account, hash, force) => {
|
|
749
|
+
clearStaleStore();
|
|
750
|
+
_permitStore.setState(
|
|
751
|
+
produce((state) => {
|
|
752
|
+
if (state.permits[chainId] == null)
|
|
753
|
+
state.permits[chainId] = {};
|
|
754
|
+
if (state.activePermitHash[chainId] == null)
|
|
755
|
+
state.activePermitHash[chainId] = {};
|
|
756
|
+
const accountPermits = state.permits[chainId][account];
|
|
757
|
+
if (accountPermits == null)
|
|
758
|
+
return;
|
|
759
|
+
if (accountPermits[hash] == null)
|
|
760
|
+
return;
|
|
761
|
+
if (state.activePermitHash[chainId][account] === hash) {
|
|
762
|
+
const otherPermitHash = Object.keys(accountPermits).find((key) => key !== hash && accountPermits[key] != null);
|
|
763
|
+
if (otherPermitHash) {
|
|
764
|
+
state.activePermitHash[chainId][account] = otherPermitHash;
|
|
765
|
+
} else {
|
|
766
|
+
if (!force) {
|
|
767
|
+
throw new Error("Cannot remove the last permit without force flag");
|
|
768
|
+
}
|
|
769
|
+
state.activePermitHash[chainId][account] = void 0;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
accountPermits[hash] = void 0;
|
|
773
|
+
})
|
|
774
|
+
);
|
|
775
|
+
};
|
|
776
|
+
var getActivePermitHash = (chainId, account) => {
|
|
777
|
+
clearStaleStore();
|
|
778
|
+
if (chainId == null || account == null)
|
|
779
|
+
return void 0;
|
|
780
|
+
return _permitStore.getState().activePermitHash[chainId]?.[account];
|
|
781
|
+
};
|
|
782
|
+
var setActivePermitHash = (chainId, account, hash) => {
|
|
783
|
+
clearStaleStore();
|
|
784
|
+
_permitStore.setState(
|
|
785
|
+
produce((state) => {
|
|
786
|
+
if (state.activePermitHash[chainId] == null)
|
|
787
|
+
state.activePermitHash[chainId] = {};
|
|
788
|
+
state.activePermitHash[chainId][account] = hash;
|
|
789
|
+
})
|
|
790
|
+
);
|
|
791
|
+
};
|
|
792
|
+
var removeActivePermitHash = (chainId, account) => {
|
|
793
|
+
clearStaleStore();
|
|
794
|
+
_permitStore.setState(
|
|
795
|
+
produce((state) => {
|
|
796
|
+
if (state.activePermitHash[chainId])
|
|
797
|
+
state.activePermitHash[chainId][account] = void 0;
|
|
798
|
+
})
|
|
799
|
+
);
|
|
800
|
+
};
|
|
801
|
+
var resetStore = () => {
|
|
802
|
+
clearStaleStore();
|
|
803
|
+
_permitStore.setState({ permits: {}, activePermitHash: {} });
|
|
804
|
+
};
|
|
805
|
+
var permitStore = {
|
|
806
|
+
store: _permitStore,
|
|
807
|
+
getPermit,
|
|
808
|
+
getActivePermit,
|
|
809
|
+
getPermits,
|
|
810
|
+
setPermit,
|
|
811
|
+
removePermit,
|
|
812
|
+
getActivePermitHash,
|
|
813
|
+
setActivePermitHash,
|
|
814
|
+
removeActivePermitHash,
|
|
815
|
+
resetStore
|
|
816
|
+
};
|
|
817
|
+
|
|
818
|
+
export { GenerateSealingKey, ImportPermitOptionsValidator, ImportPermitValidator, PERMIT_STORE_DEFAULTS, 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 };
|