@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,477 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
PermitUtils,
|
|
4
|
+
type CreateSelfPermitOptions,
|
|
5
|
+
type CreateSharingPermitOptions,
|
|
6
|
+
type ImportSharedPermitOptions,
|
|
7
|
+
} from './index.js';
|
|
8
|
+
import { createPublicClient, createWalletClient, http, type PublicClient, type WalletClient } from 'viem';
|
|
9
|
+
import { arbitrumSepolia } from 'viem/chains';
|
|
10
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
11
|
+
|
|
12
|
+
// Test private keys (well-known test keys from Anvil/Hardhat)
|
|
13
|
+
const BOB_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'; // Bob - always issuer
|
|
14
|
+
const ALICE_PRIVATE_KEY = '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d'; // Alice - always recipient
|
|
15
|
+
|
|
16
|
+
// Create real viem clients for Arbitrum Sepolia
|
|
17
|
+
const publicClient: PublicClient = createPublicClient({
|
|
18
|
+
chain: arbitrumSepolia,
|
|
19
|
+
transport: http(),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const bobWalletClient: WalletClient = createWalletClient({
|
|
23
|
+
chain: arbitrumSepolia,
|
|
24
|
+
transport: http(),
|
|
25
|
+
account: privateKeyToAccount(BOB_PRIVATE_KEY),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const aliceWalletClient: WalletClient = createWalletClient({
|
|
29
|
+
chain: arbitrumSepolia,
|
|
30
|
+
transport: http(),
|
|
31
|
+
account: privateKeyToAccount(ALICE_PRIVATE_KEY),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Helper to get the wallet addresses
|
|
35
|
+
const bobAddress = bobWalletClient.account!.address;
|
|
36
|
+
const aliceAddress = aliceWalletClient.account!.address;
|
|
37
|
+
|
|
38
|
+
describe('PermitUtils Tests', () => {
|
|
39
|
+
describe('createSelf', () => {
|
|
40
|
+
it('should create a self permit with valid options', async () => {
|
|
41
|
+
const options: CreateSelfPermitOptions = {
|
|
42
|
+
type: 'self',
|
|
43
|
+
issuer: bobAddress,
|
|
44
|
+
name: 'Test Permit',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const permit = PermitUtils.createSelf(options);
|
|
48
|
+
|
|
49
|
+
expect(permit.type).toBe('self');
|
|
50
|
+
expect(permit.name).toBe('Test Permit');
|
|
51
|
+
expect(permit.type).toBe('self');
|
|
52
|
+
expect(permit.issuer).toBe(bobAddress);
|
|
53
|
+
expect(permit.sealingPair).toBeDefined();
|
|
54
|
+
expect(permit.sealingPair.privateKey).toBeDefined();
|
|
55
|
+
expect(permit.sealingPair.publicKey).toBeDefined();
|
|
56
|
+
|
|
57
|
+
// Should not be signed yet
|
|
58
|
+
expect(permit.issuerSignature).toBe('0x');
|
|
59
|
+
expect(permit.recipientSignature).toBe('0x');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should throw error for invalid options', async () => {
|
|
63
|
+
const options: CreateSelfPermitOptions = {
|
|
64
|
+
type: 'self',
|
|
65
|
+
issuer: 'invalid-address',
|
|
66
|
+
name: 'Test Permit',
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
expect(() => PermitUtils.createSelf(options)).toThrowError();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('createSharing', () => {
|
|
74
|
+
it('should create a sharing permit with valid options', async () => {
|
|
75
|
+
const options: CreateSharingPermitOptions = {
|
|
76
|
+
type: 'sharing',
|
|
77
|
+
issuer: bobAddress,
|
|
78
|
+
recipient: aliceAddress,
|
|
79
|
+
name: 'Test Sharing Permit',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const permit = PermitUtils.createSharing(options);
|
|
83
|
+
|
|
84
|
+
expect(permit.type).toBe('sharing');
|
|
85
|
+
expect(permit.name).toBe('Test Sharing Permit');
|
|
86
|
+
expect(permit.type).toBe('sharing');
|
|
87
|
+
expect(permit.issuer).toBe(bobAddress);
|
|
88
|
+
expect(permit.recipient).toBe(aliceAddress);
|
|
89
|
+
expect(permit.sealingPair).toBeDefined();
|
|
90
|
+
expect(permit.sealingPair.privateKey).toBeDefined();
|
|
91
|
+
expect(permit.sealingPair.publicKey).toBeDefined();
|
|
92
|
+
|
|
93
|
+
// Should not be signed yet
|
|
94
|
+
expect(permit.issuerSignature).toBe('0x');
|
|
95
|
+
expect(permit.recipientSignature).toBe('0x');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should throw error for invalid recipient', async () => {
|
|
99
|
+
const options: CreateSharingPermitOptions = {
|
|
100
|
+
type: 'sharing',
|
|
101
|
+
issuer: bobAddress,
|
|
102
|
+
recipient: 'invalid-address',
|
|
103
|
+
name: 'Test Sharing Permit',
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
expect(() => PermitUtils.createSharing(options)).toThrow();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('importShared', () => {
|
|
111
|
+
it('should import a shared permit with valid options', async () => {
|
|
112
|
+
const options: ImportSharedPermitOptions = {
|
|
113
|
+
issuer: bobAddress,
|
|
114
|
+
recipient: aliceAddress,
|
|
115
|
+
issuerSignature: '0x1234567890abcdef',
|
|
116
|
+
name: 'Test Import Permit',
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const permit = PermitUtils.importShared(options);
|
|
120
|
+
|
|
121
|
+
expect(permit.type).toBe('recipient');
|
|
122
|
+
expect(permit.name).toBe('Test Import Permit');
|
|
123
|
+
expect(permit.issuer).toBe(bobAddress);
|
|
124
|
+
expect(permit.recipient).toBe(aliceAddress);
|
|
125
|
+
expect(permit.issuerSignature).toBe('0x1234567890abcdef');
|
|
126
|
+
expect(permit.sealingPair).toBeDefined();
|
|
127
|
+
expect(permit.sealingPair.privateKey).toBeDefined();
|
|
128
|
+
expect(permit.sealingPair.publicKey).toBeDefined();
|
|
129
|
+
|
|
130
|
+
// Should not be signed yet
|
|
131
|
+
expect(permit.recipientSignature).toBe('0x');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should import a shared permit with valid options as string', async () => {
|
|
135
|
+
const options: ImportSharedPermitOptions = {
|
|
136
|
+
issuer: bobAddress,
|
|
137
|
+
recipient: aliceAddress,
|
|
138
|
+
issuerSignature: '0x1234567890abcdef',
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const stringOptions = JSON.stringify(options);
|
|
142
|
+
|
|
143
|
+
const permit = PermitUtils.importShared(stringOptions);
|
|
144
|
+
|
|
145
|
+
expect(permit.type).toBe('recipient');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should throw error for invalid permit type', async () => {
|
|
149
|
+
const options = {
|
|
150
|
+
type: 'self',
|
|
151
|
+
issuer: bobAddress,
|
|
152
|
+
recipient: aliceAddress,
|
|
153
|
+
issuerSignature: '0x1234567890abcdef',
|
|
154
|
+
} as unknown as ImportSharedPermitOptions;
|
|
155
|
+
|
|
156
|
+
expect(() => PermitUtils.importShared(options)).toThrow();
|
|
157
|
+
|
|
158
|
+
const options2 = {
|
|
159
|
+
type: 'recipient',
|
|
160
|
+
issuer: bobAddress,
|
|
161
|
+
recipient: aliceAddress,
|
|
162
|
+
issuerSignature: '0x1234567890abcdef',
|
|
163
|
+
} as unknown as ImportSharedPermitOptions;
|
|
164
|
+
|
|
165
|
+
expect(() => PermitUtils.importShared(options2)).toThrow();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should throw error for missing issuerSignature', async () => {
|
|
169
|
+
const options: ImportSharedPermitOptions = {
|
|
170
|
+
issuer: bobAddress,
|
|
171
|
+
recipient: aliceAddress,
|
|
172
|
+
issuerSignature: '0x', // Invalid empty signature
|
|
173
|
+
name: 'Test Import Permit',
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
expect(() => PermitUtils.importShared(options)).toThrow();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('createSelfAndSign', () => {
|
|
181
|
+
it('should create and sign a self permit', async () => {
|
|
182
|
+
const options: CreateSelfPermitOptions = {
|
|
183
|
+
issuer: bobAddress,
|
|
184
|
+
name: 'Test Permit',
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const permit = await PermitUtils.createSelfAndSign(options, publicClient, bobWalletClient);
|
|
188
|
+
|
|
189
|
+
expect(permit.type).toBe('self');
|
|
190
|
+
expect(permit.issuerSignature).toBeDefined();
|
|
191
|
+
expect(permit.issuerSignature).not.toBe('0x');
|
|
192
|
+
expect(permit.recipientSignature).toBe('0x');
|
|
193
|
+
expect(permit._signedDomain).toBeDefined();
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('createSharingAndSign', () => {
|
|
198
|
+
it('should create and sign a sharing permit', async () => {
|
|
199
|
+
const options: CreateSharingPermitOptions = {
|
|
200
|
+
issuer: bobAddress,
|
|
201
|
+
recipient: aliceAddress,
|
|
202
|
+
name: 'Test Sharing Permit',
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const permit = await PermitUtils.createSharingAndSign(options, publicClient, bobWalletClient);
|
|
206
|
+
|
|
207
|
+
expect(permit.type).toBe('sharing');
|
|
208
|
+
expect(permit.issuerSignature).toBeDefined();
|
|
209
|
+
expect(permit.issuerSignature).not.toBe('0x');
|
|
210
|
+
expect(permit.recipientSignature).toBe('0x');
|
|
211
|
+
expect(permit._signedDomain).toBeDefined();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
describe('importSharedAndSign', () => {
|
|
216
|
+
it('should import and sign a shared permit', async () => {
|
|
217
|
+
const options: ImportSharedPermitOptions = {
|
|
218
|
+
issuer: bobAddress,
|
|
219
|
+
recipient: aliceAddress,
|
|
220
|
+
issuerSignature: '0x1234567890abcdef',
|
|
221
|
+
name: 'Test Import Permit',
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const permit = await PermitUtils.importSharedAndSign(options, publicClient, aliceWalletClient);
|
|
225
|
+
|
|
226
|
+
expect(permit.type).toBe('recipient');
|
|
227
|
+
expect(permit.recipientSignature).toBeDefined();
|
|
228
|
+
expect(permit.recipientSignature).not.toBe('0x');
|
|
229
|
+
expect(permit._signedDomain).toBeDefined();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should import and sign a shared permit string', async () => {
|
|
233
|
+
const options: ImportSharedPermitOptions = {
|
|
234
|
+
issuer: bobAddress,
|
|
235
|
+
recipient: aliceAddress,
|
|
236
|
+
issuerSignature: '0x1234567890abcdef',
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const stringOptions = JSON.stringify(options);
|
|
240
|
+
|
|
241
|
+
const permit = await PermitUtils.importSharedAndSign(stringOptions, publicClient, aliceWalletClient);
|
|
242
|
+
|
|
243
|
+
expect(permit.type).toBe('recipient');
|
|
244
|
+
expect(permit.recipientSignature).toBeDefined();
|
|
245
|
+
expect(permit.recipientSignature).not.toBe('0x');
|
|
246
|
+
expect(permit._signedDomain).toBeDefined();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('should import and sign a shared permit json object', async () => {
|
|
250
|
+
const options: ImportSharedPermitOptions = {
|
|
251
|
+
issuer: bobAddress,
|
|
252
|
+
recipient: aliceAddress,
|
|
253
|
+
issuerSignature: '0x1234567890abcdef',
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const jsonOptions = JSON.parse(JSON.stringify(options));
|
|
257
|
+
|
|
258
|
+
const permit = await PermitUtils.importSharedAndSign(jsonOptions, publicClient, aliceWalletClient);
|
|
259
|
+
|
|
260
|
+
expect(permit.type).toBe('recipient');
|
|
261
|
+
expect(permit.recipientSignature).toBeDefined();
|
|
262
|
+
expect(permit.recipientSignature).not.toBe('0x');
|
|
263
|
+
expect(permit._signedDomain).toBeDefined();
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe('sign', () => {
|
|
268
|
+
it('should sign a self permit', async () => {
|
|
269
|
+
const permit = PermitUtils.createSelf({
|
|
270
|
+
issuer: bobAddress,
|
|
271
|
+
name: 'Test Permit',
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const signedPermit = await PermitUtils.sign(permit, publicClient, bobWalletClient);
|
|
275
|
+
|
|
276
|
+
expect(signedPermit.type).toBe('self');
|
|
277
|
+
expect(signedPermit.issuerSignature).toBeDefined();
|
|
278
|
+
expect(signedPermit.issuerSignature).not.toBe('0x');
|
|
279
|
+
expect(signedPermit._signedDomain).toBeDefined();
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('should sign a recipient permit', async () => {
|
|
283
|
+
const permit = PermitUtils.importShared({
|
|
284
|
+
issuer: bobAddress,
|
|
285
|
+
recipient: aliceAddress,
|
|
286
|
+
issuerSignature: '0xexisting-signature',
|
|
287
|
+
name: 'Test Permit',
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const signedPermit = await PermitUtils.sign(permit, publicClient, aliceWalletClient);
|
|
291
|
+
|
|
292
|
+
expect(signedPermit.recipientSignature).toBeDefined();
|
|
293
|
+
expect(signedPermit.recipientSignature).not.toBe('0x');
|
|
294
|
+
expect(signedPermit._signedDomain).toBeDefined();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it('should throw error for undefined signer', async () => {
|
|
298
|
+
const permit = PermitUtils.createSelf({
|
|
299
|
+
issuer: bobAddress,
|
|
300
|
+
name: 'Test Permit',
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
await expect(
|
|
304
|
+
// @ts-expect-error - undefined signer
|
|
305
|
+
PermitUtils.sign(permit, publicClient, undefined)
|
|
306
|
+
).rejects.toThrow();
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
describe('serialize/deserialize', () => {
|
|
311
|
+
it('should serialize and deserialize a permit', async () => {
|
|
312
|
+
const originalPermit = PermitUtils.createSelf({
|
|
313
|
+
issuer: bobAddress,
|
|
314
|
+
name: 'Test Permit',
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const serialized = PermitUtils.serialize(originalPermit);
|
|
318
|
+
const deserialized = PermitUtils.deserialize(serialized);
|
|
319
|
+
|
|
320
|
+
expect(deserialized.type).toBe('self');
|
|
321
|
+
expect(deserialized.name).toBe(originalPermit.name);
|
|
322
|
+
expect(deserialized.type).toBe(originalPermit.type);
|
|
323
|
+
expect(deserialized.issuer).toBe(originalPermit.issuer);
|
|
324
|
+
expect(deserialized.sealingPair.privateKey).toBe(originalPermit.sealingPair.privateKey);
|
|
325
|
+
expect(deserialized.sealingPair.publicKey).toBe(originalPermit.sealingPair.publicKey);
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
describe('getPermission', () => {
|
|
330
|
+
it('should extract permission from permit', async () => {
|
|
331
|
+
const permit = await PermitUtils.createSelfAndSign(
|
|
332
|
+
{
|
|
333
|
+
issuer: bobAddress,
|
|
334
|
+
name: 'Test Permit',
|
|
335
|
+
},
|
|
336
|
+
publicClient,
|
|
337
|
+
bobWalletClient
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
const permission = PermitUtils.getPermission(permit);
|
|
341
|
+
|
|
342
|
+
expect(permission.issuer).toBe(permit.issuer);
|
|
343
|
+
expect(permission.sealingKey).toBe(`0x${permit.sealingPair.publicKey}`);
|
|
344
|
+
expect(permission).not.toHaveProperty('name');
|
|
345
|
+
expect(permission).not.toHaveProperty('type');
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
describe('getHash', () => {
|
|
350
|
+
it('should generate consistent hash for same permit data', async () => {
|
|
351
|
+
const expiration = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now
|
|
352
|
+
const permit1 = PermitUtils.createSelf({
|
|
353
|
+
expiration,
|
|
354
|
+
issuer: bobAddress,
|
|
355
|
+
name: 'Test Permit',
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
const permit2 = PermitUtils.createSelf({
|
|
359
|
+
expiration,
|
|
360
|
+
issuer: bobAddress,
|
|
361
|
+
name: 'Test Permit',
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const hash1 = PermitUtils.getHash(permit1);
|
|
365
|
+
const hash2 = PermitUtils.getHash(permit2);
|
|
366
|
+
|
|
367
|
+
expect(hash1).toBe(hash2);
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
describe('export', () => {
|
|
372
|
+
it('should export permit data without sensitive fields', async () => {
|
|
373
|
+
const permit = PermitUtils.createSelf({
|
|
374
|
+
issuer: bobAddress,
|
|
375
|
+
name: 'Test Permit',
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
const exported = PermitUtils.export(permit);
|
|
379
|
+
const parsed = JSON.parse(exported);
|
|
380
|
+
|
|
381
|
+
expect(parsed.name).toBe('Test Permit');
|
|
382
|
+
expect(parsed.issuer).toBe(bobAddress);
|
|
383
|
+
expect(parsed).not.toHaveProperty('sealingPair');
|
|
384
|
+
expect(parsed).not.toHaveProperty('issuerSignature');
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
describe('updateName', () => {
|
|
389
|
+
it('should update permit name immutably', async () => {
|
|
390
|
+
const permit = PermitUtils.createSelf({
|
|
391
|
+
issuer: bobAddress,
|
|
392
|
+
name: 'Original Name',
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
const updatedPermit = PermitUtils.updateName(permit, 'New Name');
|
|
396
|
+
|
|
397
|
+
expect(updatedPermit.name).toBe('New Name');
|
|
398
|
+
expect(permit.name).toBe('Original Name'); // Original should be unchanged
|
|
399
|
+
expect(updatedPermit).not.toBe(permit); // Should be a new object
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
describe('validation helpers', () => {
|
|
404
|
+
it('should check if permit is expired', async () => {
|
|
405
|
+
const expiredPermit = PermitUtils.createSelf({
|
|
406
|
+
issuer: bobAddress,
|
|
407
|
+
name: 'Test Permit',
|
|
408
|
+
expiration: Math.floor(Date.now() / 1000) - 3600, // 1 hour ago
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
const validPermit = PermitUtils.createSelf({
|
|
412
|
+
issuer: bobAddress,
|
|
413
|
+
name: 'Test Permit',
|
|
414
|
+
expiration: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
expect(PermitUtils.isExpired(expiredPermit)).toBe(true);
|
|
418
|
+
expect(PermitUtils.isExpired(validPermit)).toBe(false);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it('should check if permit is signed', async () => {
|
|
422
|
+
const unsignedPermit = PermitUtils.createSelf({
|
|
423
|
+
issuer: bobAddress,
|
|
424
|
+
name: 'Test Permit',
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
const signedPermit = await PermitUtils.sign(unsignedPermit, publicClient, bobWalletClient);
|
|
428
|
+
|
|
429
|
+
expect(PermitUtils.isSigned(unsignedPermit)).toBe(false);
|
|
430
|
+
expect(PermitUtils.isSigned(signedPermit)).toBe(true);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it('should check overall validity', async () => {
|
|
434
|
+
const validPermit = PermitUtils.createSelf({
|
|
435
|
+
issuer: bobAddress,
|
|
436
|
+
name: 'Test Permit',
|
|
437
|
+
expiration: Math.floor(Date.now() / 1000) + 3600,
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const signedPermit = await PermitUtils.sign(validPermit, publicClient, bobWalletClient);
|
|
441
|
+
|
|
442
|
+
const validation = PermitUtils.isValid(signedPermit);
|
|
443
|
+
expect(validation.valid).toBe(true);
|
|
444
|
+
expect(validation.error).toBeNull();
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
describe('real contract interactions', () => {
|
|
449
|
+
it('should fetch EIP712 domain from real Arbitrum Sepolia contract', async () => {
|
|
450
|
+
// This test uses the real public client to fetch actual contract data
|
|
451
|
+
const domain = await PermitUtils.fetchEIP712Domain(publicClient);
|
|
452
|
+
|
|
453
|
+
expect(domain).toBeDefined();
|
|
454
|
+
expect(domain.name).toBeDefined();
|
|
455
|
+
expect(domain.version).toBeDefined();
|
|
456
|
+
expect(domain.chainId).toBeDefined();
|
|
457
|
+
expect(domain.verifyingContract).toBeDefined();
|
|
458
|
+
expect(domain.verifyingContract).toMatch(/^0x[a-fA-F0-9]{40}$/); // Valid Ethereum address
|
|
459
|
+
}, 10000); // 10 second timeout for network call
|
|
460
|
+
|
|
461
|
+
it('should check signed domain validity with real contract data', async () => {
|
|
462
|
+
const permit = PermitUtils.createSelf({
|
|
463
|
+
type: 'self',
|
|
464
|
+
issuer: bobAddress,
|
|
465
|
+
name: 'Test Permit',
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// Sign the permit to get a domain
|
|
469
|
+
const signedPermit = await PermitUtils.sign(permit, publicClient, bobWalletClient);
|
|
470
|
+
|
|
471
|
+
// Check if the signed domain is valid against the real contract
|
|
472
|
+
const isValid = await PermitUtils.checkSignedDomainValid(signedPermit, publicClient);
|
|
473
|
+
|
|
474
|
+
expect(typeof isValid).toBe('boolean');
|
|
475
|
+
}, 10000); // 10 second timeout for network call
|
|
476
|
+
});
|
|
477
|
+
});
|