@cofhe/sdk 0.3.2 → 0.5.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.
Files changed (97) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/adapters/{ethers5.test.ts → test/ethers5.test.ts} +2 -2
  3. package/adapters/{ethers6.test.ts → test/ethers6.test.ts} +2 -2
  4. package/adapters/{hardhat.hh2.test.ts → test/hardhat.hh2.test.ts} +2 -2
  5. package/adapters/{index.test.ts → test/index.test.ts} +1 -1
  6. package/adapters/{wagmi.test.ts → test/wagmi.test.ts} +1 -1
  7. package/chains/{chains.test.ts → test/chains.test.ts} +1 -1
  8. package/core/client.ts +15 -5
  9. package/core/clientTypes.ts +7 -5
  10. package/core/consts.ts +9 -0
  11. package/core/decrypt/cofheMocksDecryptForTx.ts +14 -3
  12. package/core/decrypt/decryptForTxBuilder.ts +24 -10
  13. package/core/decrypt/decryptForViewBuilder.ts +14 -7
  14. package/core/decrypt/polling.ts +14 -0
  15. package/core/decrypt/tnDecryptUtils.ts +65 -0
  16. package/core/decrypt/{tnDecrypt.ts → tnDecryptV1.ts} +7 -70
  17. package/core/decrypt/tnDecryptV2.ts +483 -0
  18. package/core/decrypt/tnSealOutputV2.ts +245 -104
  19. package/core/decrypt/verifyDecryptResult.ts +65 -0
  20. package/core/encrypt/cofheMocksZkVerifySign.ts +6 -6
  21. package/core/encrypt/zkPackProveVerify.ts +10 -19
  22. package/core/fetchKeys.ts +0 -2
  23. package/core/index.ts +9 -1
  24. package/core/keyStore.ts +5 -2
  25. package/core/permits.ts +8 -3
  26. package/core/{client.test.ts → test/client.test.ts} +7 -7
  27. package/core/{config.test.ts → test/config.test.ts} +1 -1
  28. package/core/test/decrypt.test.ts +252 -0
  29. package/core/test/decryptBuilders.test.ts +390 -0
  30. package/core/{encrypt → test}/encryptInputsBuilder.test.ts +61 -6
  31. package/core/{fetchKeys.test.ts → test/fetchKeys.test.ts} +3 -3
  32. package/core/{keyStore.test.ts → test/keyStore.test.ts} +5 -3
  33. package/core/{permits.test.ts → test/permits.test.ts} +42 -1
  34. package/core/test/pollCallbacks.test.ts +563 -0
  35. package/core/types.ts +21 -0
  36. package/dist/chains.d.cts +2 -2
  37. package/dist/chains.d.ts +2 -2
  38. package/dist/chunk-4FP4V35O.js +13 -0
  39. package/dist/{chunk-NWDKXBIP.js → chunk-MRCKUMOS.js} +62 -22
  40. package/dist/{chunk-LWMRB6SD.js → chunk-S7OKGLFD.js} +615 -198
  41. package/dist/{clientTypes-Y43CKbOz.d.cts → clientTypes-BSbwairE.d.cts} +38 -13
  42. package/dist/{clientTypes-PQha8zes.d.ts → clientTypes-DDmcgZ0a.d.ts} +38 -13
  43. package/dist/core.cjs +691 -235
  44. package/dist/core.d.cts +24 -6
  45. package/dist/core.d.ts +24 -6
  46. package/dist/core.js +3 -2
  47. package/dist/node.cjs +696 -237
  48. package/dist/node.d.cts +3 -3
  49. package/dist/node.d.ts +3 -3
  50. package/dist/node.js +14 -7
  51. package/dist/{permit-MZ502UBl.d.ts → permit-DnVMDT5h.d.cts} +34 -4
  52. package/dist/{permit-MZ502UBl.d.cts → permit-DnVMDT5h.d.ts} +34 -4
  53. package/dist/permits.cjs +66 -29
  54. package/dist/permits.d.cts +18 -13
  55. package/dist/permits.d.ts +18 -13
  56. package/dist/permits.js +2 -1
  57. package/dist/web.cjs +718 -242
  58. package/dist/web.d.cts +8 -4
  59. package/dist/web.d.ts +8 -4
  60. package/dist/web.js +34 -11
  61. package/dist/zkProve.worker.cjs +6 -3
  62. package/dist/zkProve.worker.js +5 -3
  63. package/node/index.ts +13 -4
  64. package/node/test/client.test.ts +25 -0
  65. package/node/test/config.test.ts +16 -0
  66. package/node/test/inherited.test.ts +244 -0
  67. package/node/test/tfheinit.test.ts +56 -0
  68. package/package.json +24 -22
  69. package/permits/permit.ts +31 -5
  70. package/permits/sealing.ts +1 -1
  71. package/permits/{localstorage.test.ts → test/localstorage.test.ts} +2 -2
  72. package/permits/{permit.test.ts → test/permit.test.ts} +35 -1
  73. package/permits/{sealing.test.ts → test/sealing.test.ts} +1 -1
  74. package/permits/{store.test.ts → test/store.test.ts} +2 -2
  75. package/permits/{validation.test.ts → test/validation.test.ts} +82 -6
  76. package/permits/types.ts +1 -1
  77. package/permits/validation.ts +42 -2
  78. package/web/const.ts +2 -0
  79. package/web/index.ts +20 -6
  80. package/web/storage.ts +18 -3
  81. package/web/{client.web.test.ts → test/client.web.test.ts} +13 -1
  82. package/web/test/config.web.test.ts +16 -0
  83. package/web/test/inherited.web.test.ts +245 -0
  84. package/web/test/tfheinit.web.test.ts +62 -0
  85. package/web/{worker.config.web.test.ts → test/worker.config.web.test.ts} +1 -1
  86. package/web/{worker.output.web.test.ts → test/worker.output.web.test.ts} +1 -1
  87. package/web/{workerManager.test.ts → test/workerManager.test.ts} +1 -1
  88. package/web/{workerManager.web.test.ts → test/workerManager.web.test.ts} +1 -1
  89. package/web/zkProve.worker.ts +4 -3
  90. package/node/client.test.ts +0 -147
  91. package/node/config.test.ts +0 -68
  92. package/node/encryptInputs.test.ts +0 -155
  93. package/web/config.web.test.ts +0 -69
  94. package/web/encryptInputs.web.test.ts +0 -172
  95. package/web/worker.builder.web.test.ts +0 -148
  96. /package/dist/{types-YiAC4gig.d.cts → types-C07FK-cL.d.cts} +0 -0
  97. /package/dist/{types-YiAC4gig.d.ts → types-C07FK-cL.d.ts} +0 -0
package/core/permits.ts CHANGED
@@ -75,6 +75,10 @@ const getHash = (permit: PermitHashFields) => {
75
75
  return PermitUtils.getHash(permit);
76
76
  };
77
77
 
78
+ const exportShared = (permit: Permit) => {
79
+ return PermitUtils.export(permit);
80
+ };
81
+
78
82
  const serialize = (permit: Permit) => {
79
83
  return PermitUtils.serialize(permit);
80
84
  };
@@ -85,15 +89,15 @@ const deserialize = (serialized: SerializedPermit) => {
85
89
 
86
90
  // GET
87
91
 
88
- const getPermit = async (chainId: number, account: string, hash: string): Promise<Permit | undefined> => {
92
+ const getPermit = (chainId: number, account: string, hash: string): Permit | undefined => {
89
93
  return permitStore.getPermit(chainId, account, hash);
90
94
  };
91
95
 
92
- const getPermits = async (chainId: number, account: string): Promise<Record<string, Permit>> => {
96
+ const getPermits = (chainId: number, account: string): Record<string, Permit> => {
93
97
  return permitStore.getPermits(chainId, account);
94
98
  };
95
99
 
96
- const getActivePermit = async (chainId: number, account: string): Promise<Permit | undefined> => {
100
+ const getActivePermit = (chainId: number, account: string): Permit | undefined => {
97
101
  return permitStore.getActivePermit(chainId, account);
98
102
  };
99
103
 
@@ -188,6 +192,7 @@ export const permits = {
188
192
  getOrCreateSharingPermit,
189
193
 
190
194
  getHash,
195
+ export: exportShared,
191
196
  serialize,
192
197
  deserialize,
193
198
 
@@ -1,14 +1,14 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { createCofheClientBase } from './client.js';
3
- import { type CofheClient, type CofheClientConnectionState } from './clientTypes.js';
4
- import { createCofheConfigBase, type CofheEnvironment } from './config.js';
5
- import { CofheError, CofheErrorCode } from './error.js';
2
+ import { createCofheClientBase } from '../client.js';
3
+ import { type CofheClient, type CofheClientConnectionState } from '../clientTypes.js';
4
+ import { createCofheConfigBase, type CofheEnvironment } from '../config.js';
5
+ import { CofheError, CofheErrorCode } from '../error.js';
6
6
  import { type PublicClient, type WalletClient } from 'viem';
7
- import { EncryptInputsBuilder } from './encrypt/encryptInputsBuilder.js';
8
- import { Encryptable } from './types.js';
7
+ import { EncryptInputsBuilder } from '../encrypt/encryptInputsBuilder.js';
8
+ import { Encryptable } from '../types.js';
9
9
 
10
10
  // Mock dependencies
11
- vi.mock('./keyStore', () => ({
11
+ vi.mock('../keyStore', () => ({
12
12
  createKeysStore: vi.fn(() => ({
13
13
  rehydrateKeysStore: vi.fn().mockResolvedValue(undefined),
14
14
  getFheKey: vi.fn(),
@@ -9,7 +9,7 @@ import {
9
9
  getCoFheUrlOrThrow,
10
10
  getZkVerifierUrlOrThrow,
11
11
  getThresholdNetworkUrlOrThrow,
12
- } from './config.js';
12
+ } from '../config.js';
13
13
 
14
14
  describe('createCofheConfigBase', () => {
15
15
  const validBaseConfig: CofheInputConfig = {
@@ -0,0 +1,252 @@
1
+ import { FheTypes, verifyDecryptResult, createCofheConfigBase, TASK_MANAGER_ADDRESS } from '@/core';
2
+ import { getChainById } from '@/chains';
3
+ import {
4
+ TEST_PRIVATE_KEY,
5
+ PRIMARY_TEST_CHAIN,
6
+ primaryTestChainRegistry,
7
+ isPrimaryTestChainReady,
8
+ } from '@cofhe/test-setup';
9
+
10
+ import { permits } from '../permits.js';
11
+ import { DecryptForTxBuilder } from '../decrypt/decryptForTxBuilder.js';
12
+ import { DecryptForViewBuilder } from '../decrypt/decryptForViewBuilder.js';
13
+
14
+ import { describe, it, expect, beforeAll } from 'vitest';
15
+ import type { Chain, PublicClient, WalletClient } from 'viem';
16
+ import { createPublicClient, createWalletClient, http, parseAbi } from 'viem';
17
+ import { privateKeyToAccount } from 'viem/accounts';
18
+ import { arbitrumSepolia, baseSepolia, sepolia } from 'viem/chains';
19
+
20
+ const account = privateKeyToAccount(TEST_PRIVATE_KEY);
21
+
22
+ const VIEM_CHAINS: Record<number, Chain> = {
23
+ 421614: arbitrumSepolia,
24
+ 84532: baseSepolia,
25
+ 11155111: sepolia,
26
+ };
27
+
28
+ describe('Core – Decrypt Tests', () => {
29
+ let publicClient: PublicClient;
30
+ let walletClient: WalletClient;
31
+ let config: ReturnType<typeof createCofheConfigBase>;
32
+
33
+ let privateCtHash: `0x${string}`;
34
+ let privateValue: bigint;
35
+
36
+ let publicCtHash: `0x${string}`;
37
+ let publicValue: bigint;
38
+
39
+ beforeAll(() => {
40
+ if (!isPrimaryTestChainReady(primaryTestChainRegistry)) {
41
+ throw new Error('Primary test chain registry is not initialized. Run `pnpm test:setup` first.');
42
+ }
43
+
44
+ const reg = primaryTestChainRegistry;
45
+ const chainId = reg.chainId;
46
+
47
+ const viemChain = VIEM_CHAINS[chainId];
48
+ if (!viemChain) throw new Error(`No viem chain mapping for chain ${chainId}`);
49
+
50
+ const cofheChain = getChainById(chainId);
51
+ if (!cofheChain) throw new Error(`No cofhe chain config for chain ${chainId}`);
52
+
53
+ config = createCofheConfigBase({ supportedChains: [cofheChain] });
54
+
55
+ privateCtHash = reg.privateValue.ctHash as `0x${string}`;
56
+ privateValue = BigInt(reg.privateValue.value);
57
+
58
+ publicCtHash = reg.publicValue.ctHash as `0x${string}`;
59
+ publicValue = BigInt(reg.publicValue.value);
60
+
61
+ publicClient = createPublicClient({ chain: viemChain, transport: http() });
62
+ walletClient = createWalletClient({ chain: viemChain, transport: http(), account });
63
+ });
64
+
65
+ function txBuilder(ctHash: `0x${string}`) {
66
+ return new DecryptForTxBuilder({
67
+ config,
68
+ publicClient,
69
+ walletClient,
70
+ chainId: PRIMARY_TEST_CHAIN,
71
+ account: account.address,
72
+ ctHash,
73
+ requireConnected: undefined,
74
+ });
75
+ }
76
+
77
+ function viewBuilder(ctHash: `0x${string}`, utype: FheTypes) {
78
+ return new DecryptForViewBuilder({
79
+ config,
80
+ publicClient,
81
+ walletClient,
82
+ chainId: PRIMARY_TEST_CHAIN,
83
+ account: account.address,
84
+ ctHash,
85
+ utype,
86
+ requireConnected: undefined,
87
+ });
88
+ }
89
+
90
+ async function createPermit() {
91
+ return permits.createSelf({ issuer: account.address, name: 'Decrypt Test Permit' }, publicClient, walletClient);
92
+ }
93
+
94
+ // ---------------------------------------------------------------------------
95
+ // decryptForTx – withoutPermit (global allowance)
96
+ // ---------------------------------------------------------------------------
97
+
98
+ describe('decryptForTx – withoutPermit (global allowance)', () => {
99
+ it('should decrypt a publicly allowed ciphertext', async () => {
100
+ const result = await txBuilder(publicCtHash).withoutPermit().execute();
101
+
102
+ expect(BigInt(result.ctHash)).toBe(BigInt(publicCtHash));
103
+ expect(result.decryptedValue).toBe(publicValue);
104
+ expect(result.signature).toMatch(/^0x[0-9a-fA-F]+$/);
105
+ }, 180000);
106
+ });
107
+
108
+ // ---------------------------------------------------------------------------
109
+ // decryptForTx – withPermit
110
+ // ---------------------------------------------------------------------------
111
+
112
+ describe('decryptForTx – withPermit', () => {
113
+ it('should decrypt with a self permit', async () => {
114
+ const permit = await createPermit();
115
+
116
+ const result = await txBuilder(privateCtHash).withPermit(permit).execute();
117
+
118
+ expect(BigInt(result.ctHash)).toBe(BigInt(privateCtHash));
119
+ expect(result.decryptedValue).toBe(privateValue);
120
+ expect(result.signature).toBeDefined();
121
+ }, 180000);
122
+
123
+ it('should auto-resolve active permit', async () => {
124
+ const permit = await createPermit();
125
+ permits.selectActivePermit(PRIMARY_TEST_CHAIN, account.address, permit.hash);
126
+
127
+ const result = await txBuilder(privateCtHash).withPermit().execute();
128
+
129
+ expect(BigInt(result.ctHash)).toBe(BigInt(privateCtHash));
130
+ expect(result.decryptedValue).toBe(privateValue);
131
+ }, 180000);
132
+ });
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // verifyDecryptResult
136
+ // ---------------------------------------------------------------------------
137
+
138
+ describe('verifyDecryptResult', () => {
139
+ it('should verify a valid decrypt result', async () => {
140
+ const permit = await createPermit();
141
+
142
+ const decryptResult = await txBuilder(privateCtHash).withPermit(permit).execute();
143
+
144
+ const isValid = await verifyDecryptResult(
145
+ decryptResult.ctHash,
146
+ privateValue,
147
+ decryptResult.signature,
148
+ publicClient
149
+ );
150
+ expect(isValid).toBe(true);
151
+ }, 180000);
152
+
153
+ it('should return false for invalid inputs', async () => {
154
+ const permit = await createPermit();
155
+
156
+ const decryptResult = await txBuilder(privateCtHash).withPermit(permit).execute();
157
+
158
+ expect(
159
+ await verifyDecryptResult(decryptResult.ctHash, privateValue + 1n, decryptResult.signature, publicClient)
160
+ ).toBe(false);
161
+ }, 180000);
162
+ });
163
+
164
+ // ---------------------------------------------------------------------------
165
+ // decryptForView
166
+ // ---------------------------------------------------------------------------
167
+
168
+ describe('decryptForView', () => {
169
+ it('should return the plaintext value', async () => {
170
+ await createPermit();
171
+
172
+ const result = await viewBuilder(privateCtHash, FheTypes.Uint32).execute();
173
+ expect(result).toBe(privateValue);
174
+ }, 180000);
175
+
176
+ it('should agree with decryptForTx on the same handle', async () => {
177
+ const permit = await createPermit();
178
+
179
+ const viewResult = await viewBuilder(privateCtHash, FheTypes.Uint32).execute();
180
+ const txResult = await txBuilder(privateCtHash).withPermit(permit).execute();
181
+
182
+ expect(viewResult).toBe(privateValue);
183
+ expect(BigInt(txResult.ctHash)).toBe(BigInt(privateCtHash));
184
+ expect(txResult.decryptedValue).toBe(privateValue);
185
+ }, 180000);
186
+ });
187
+
188
+ describe('verifyDecryptResult', () => {
189
+ it('should correctly verify a valid decrypt result', async () => {
190
+ const permit = await createPermit();
191
+
192
+ const decryptResult = await txBuilder(privateCtHash).withPermit(permit).execute();
193
+
194
+ const isValid = await verifyDecryptResult(
195
+ decryptResult.ctHash,
196
+ privateValue,
197
+ decryptResult.signature,
198
+ publicClient
199
+ );
200
+ expect(isValid).toBe(true);
201
+ }, 180000);
202
+
203
+ it('should verify identically to the on-chain TaskManager contract', async () => {
204
+ const permit = await createPermit();
205
+ const decryptResult = await txBuilder(privateCtHash).withPermit(permit).execute();
206
+
207
+ const samples = [
208
+ {
209
+ shouldBe: true,
210
+ handle: BigInt(decryptResult.ctHash),
211
+ cleartext: decryptResult.decryptedValue,
212
+ signature: decryptResult.signature,
213
+ },
214
+ {
215
+ shouldBe: false,
216
+ handle: BigInt(decryptResult.ctHash),
217
+ cleartext: decryptResult.decryptedValue + 1n,
218
+ signature: decryptResult.signature,
219
+ },
220
+ {
221
+ shouldBe: false,
222
+ handle: BigInt(decryptResult.ctHash) + 1n,
223
+ cleartext: decryptResult.decryptedValue,
224
+ signature: decryptResult.signature,
225
+ },
226
+ {
227
+ shouldBe: false,
228
+ handle: BigInt(decryptResult.ctHash),
229
+ cleartext: decryptResult.decryptedValue,
230
+ signature: `${decryptResult.signature}00`,
231
+ },
232
+ ] as const;
233
+
234
+ for (const sample of samples) {
235
+ const sdkResult = await verifyDecryptResult(sample.handle, sample.cleartext, sample.signature, publicClient);
236
+
237
+ const verifyDecryptResultSafeAbi = parseAbi([
238
+ 'function verifyDecryptResultSafe(uint256 ctHash, uint256 cleartext, bytes signature) view returns (bool)',
239
+ ]);
240
+ const tmResult = await publicClient.readContract({
241
+ address: TASK_MANAGER_ADDRESS,
242
+ abi: verifyDecryptResultSafeAbi,
243
+ functionName: 'verifyDecryptResultSafe',
244
+ args: [sample.handle, sample.cleartext, sample.signature],
245
+ });
246
+
247
+ expect(sdkResult).to.equal(tmResult);
248
+ expect(sdkResult).to.equal(sample.shouldBe);
249
+ }
250
+ });
251
+ });
252
+ });